Upload
rajesh-pal
View
229
Download
0
Embed Size (px)
Citation preview
8/3/2019 Python_Tips & Tricks
1/45
Python: Tips & Tricks
Prashant SinghNHST
8/3/2019 Python_Tips & Tricks
2/45
Agenda
The main purpose of this presentation is to make audience
familiar with some python tips and tricks that includes
some shorthand's for common tasks in programming &
miscellaneous topic.
8/3/2019 Python_Tips & Tricks
3/45
Quick Tricks
Python provides various in-build data structures for easing up programming .
Most common are:-
1. List2. Set
3. Dictionary
4. Touple
8/3/2019 Python_Tips & Tricks
4/45
Four Kinds ofQuotes
Let's start with something quick that you probably know. If you'recoming from a different language, you're probably used to using singlequotes for one thing and double quotes for another. Python lets youuse both, although not interchangeably (if you start with one, you haveto end with the same one). Python also has a two more types of quotes.
A triple
quote,
''',is cr
eat
ed by typing thr
eesingl
equot
es. A tripl
e-double quote, """, is created by typing three double quotes. So, you canhave several layers of quoting before you need to worry about escapingyour quotes. For example, this is valid Python:
print """I wish that I'd never heard him say, '''She said, "He said, 'Give me fivedollars'"'''"""
8/3/2019 Python_Tips & Tricks
5/45
Truthfulness of VariousObjects
Python types are false if empty, and true if not. That means you don'thave to check, for example, that the length of a string, tuple, list, or dictis 0 or is equal to an empty one. It is enough to just check the
truthfulness of th
eobj
ect.
As you would expect, the number zero is also false, while all othernumbers are true.
For example, the following expressions areequivalent. Here,
'my_object' is a string, but it could easily be another Python type (withappropriate modifications to theequality test)
8/3/2019 Python_Tips & Tricks
6/45
In conclusion, there's really no need to check lengths or equality ifyou're only interested in if the object is empty or not.
my_object = 'Test' # Trueexample
# my_object = '' # Falseexample
if len(my_object) > 0:print 'my_object is not empty
if len(my_object): # 0 willevaluateto Falseprint 'my object is not empty
if my_object != '':print 'my_object is not empty
if my_object: # anemptystring willevaluateto Falseprint 'my_object is not empty'
8/3/2019 Python_Tips & Tricks
7/45
Checking if a StringContainsa Substring
Here's a quick hint that might be obvious, but it took me about a yearof Python programming to figure it out.You probably know that you can test if a list, tuple, or dict contains an
item by testing theexpression 'item in list' or 'item not in list'. I neverrealized that this would work for strings as well. I was always writingcode like:
string = 'Hi there' # Trueexample# string = 'Goodbye' # Falseexample
if string.find('Hi') != -1:print 'Success!'
8/3/2019 Python_Tips & Tricks
8/45
That's some ugly code. It is completely equivalent to do'if substring in string':
Much cleaner and simpler.Might be obvious to 99% of thepopulation, but I wish I'd known about it sooner.
string = 'Hi there' # Trueexample# string = 'Goodbye' # Falseexample
if 'Hi' in string:
print 'Success!'
8/3/2019 Python_Tips & Tricks
9/45
Printing a List
Lists don't print nicely. It's of course obvious what the list is, but anaverage user doesn't want to see brackets around everything. There's atrivial solution to this, using a string's 'join' method:
Thejoin method turns the list into a string by casting each item into astring and connecting them with the string that join was called on. It'seven smart enough to not put one after the last element.
As an added advantage, this is pretty fast, running in linear time.Don't evercreate a string by '+'ing list items together in a for loop: not
only is it ugly, but it takes much longer.
recent_presidents = ['George Bush', 'Bill Clinton', 'George W. Bush']
print 'The three most recent presidents were: %s.' % ', '.join(recent_presidents)
#prints 'Thethreemost recentpresidents were: George Bush, Bill Clinton, George W.Bush.
8/3/2019 Python_Tips & Tricks
10/45
Integer vs. Float Division
By default, if you divide one integer by another, the result will betruncated into an integer. For example,executing 5/2 returns 2.
There are two was to fix this. The first and simplest way is to just turnone of the integers into a float. If the values are static, you can justappend a .0 to one to make it a float: 5.0/2 returns 2.5. Alternatively,you can just cast one of the values: float(5) / 2 returns 2.5.
8/3/2019 Python_Tips & Tricks
11/45
The other way will result in cleaner code, but you must make surenone of your code is relying on this truncation. You can do a from__future__ import division to change Python to always return a float as
the result of a division. After such an import, 5/2 will return 2.5. If youstill need to use the truncating integer division somewhere, you canthen use the // operator: 5//2 will always return 2.
Note : - At some point float division will be the default. If you wantyour code to be future-proof, use the // operator if you want truncating
division, no matter if you are doing a from __future__ importdivision or not.
5/2 # Returns 25.0/2 # Returns 2.5float(5)/2 # Returns 2.55//2 # Returns 2
from __future__import division5/2 # Returns 2.55.0/2 # Returns 2.5float(5)/2 # Returns 2.55//2 # Returns 2
8/3/2019 Python_Tips & Tricks
12/45
Lambda Functions
Sometimes you need to pass a function as an argument, or you wantto do a short but complex operation multiple times. You could defineyour function the normal way, or you could make a lambda function, amini-function that returns the result of a singleexpression. The twodefinitions are completely identical:
The advantage of the lambda function is that it is in itself anexpression, and can be used inside another statement. Here's anexample using the map function, which calls a function on every
element in a list, and returns a list of the results. (I make a good casebelow in List Comprehensions that map is pretty useless. It does,however, presents a good one lineexample.)
def add(a,b): return a+b
add2 = lambda a,b: a+b
squares = map(lambda a: a*a, [1,2,3,4,5])# squares isnow [1,4,9,16,25]
8/3/2019 Python_Tips & Tricks
13/45
Lists
List Comprehensions
If you've used Python for very long, you've at least heard of listcomprehensions. They're a way to fit a for loop, an if statement, and anassignment all in one line. In other words, you can map and filtera listin oneexpression.
8/3/2019 Python_Tips & Tricks
14/45
Mapping the ListWe'll start with something really simple. Say you're trying to square
every element in a list. A freshly-initiated Python programmer mightwrite code like this:
You'veeffectively 'mapped' one list to another list. You could also use
the
map function,and do som
ething lik
ethis:
numbers = [1,2,3,4,5]squares = []for number in numbers:
squares.append(number*number)# Now, squaresshould have [1,4,9,16,25]
numbers = [1,2,3,4,5]squares = map(lambda x: x*x, numbers)# Now, squaresshould have [1,4,9,16,25]
8/3/2019 Python_Tips & Tricks
15/45
This code is definitely shorter (1 line instead of 3) but it's pretty ugly.It's hard to tell at a glance what the map function does (it accepts a
function and a list, and applies the function to every element of thatlist). Plus, you have to give it a function of some sort which looks kindof messy. If only there were a cleaner way... perhaps a listcomprehension:
This does theexact same thing as the previous two examples, but it's
short (unlike the first example) and clean (unlike the second example).No one is going to have any problem determining what it does,even ifthey don't know Python.
numbers = [1,2,3,4,5]squares = [number*number for number in numbers]# Now, squaresshould have [1,4,9,16,25]
8/3/2019 Python_Tips & Tricks
16/45
Filtering the ListWhat if you're more interested in filtering the list? Say you want to
removeevery element with a valueequal to or greater than 4? (Okay,so theexamples aren't very realistic. Whatever...) A Python neophytemight write:
Pretty simple, right? But it took 4 lines, two degrees of nesting, and anappend to do something completely trivial. You could reduce the size ofthe code with the filter function:
numbers = [1,2,3,4,5]numbers_under_4 = []for number in numbers:
if number < 4:numbers_under_4.append(number)
# Now, numbers_under_4 contains [1,4,3]
8/3/2019 Python_Tips & Tricks
17/45
Similar to the map function we talked about above, this reduces codesize but is really ugly. What the hell is going on?Like map, filter accepts a function and a list. It evaluates for every list
element and if the function evaluates to true, that list element isincluded in the final list. Of course, we can do this with a listcomprehension as well:
Again, using a list comprehension gives us shorter, cleaner, and easierto understand code.
numbers = [1,2,3,4,5]numbers_under_4 = filter(lambda x: x < 4, numbers)
# Now, numbers_under_4 contains [1,2,3]
numbers = [1,2,3,4,5]
numbers_under_4 = [number fo
r number in numbers if number < 4]# Now, numbers_under_4 contains [1,2,3]
8/3/2019 Python_Tips & Tricks
18/45
Map and Filter at Once
Now we get to the true power of list comprehensions. If I haven't yetconvinced you that map and filter are generally a waste of your time,hopefully this will.Say I want to map and filter a list at the same time. In other words, I'dlike to see the square of each element in the list where said element isunder 4. Once more, the Python neophyte way:
The code is starting to expand in the horizontal direction now! Alas,what could we possibly do to simplify the code? We could tryusing map and filter, but I don't have a good feeling about this...
numbers = [1,2,3,4,5]squares = []for number in numbers:
if number < 4:squares.append(number*number)
# squares isnow [1,4,3]
8/3/2019 Python_Tips & Tricks
19/45
8/3/2019 Python_Tips & Tricks
20/45
Nested 'for' Statements
List comprehensions and generator expressions can be used for morethan just mapping and filtering; you can create rather complex lists oflists with them . Not only can you map and filter, you can nest the forexpressions. A python neophyte might write something like:
You can see that this code is pretty crazy. With a list comprehension,though, you can do this more quickly:
for xin (0,1,2,3):for y in (0,1,2,3):
if x < y:print (x, y,x*y),
#prints (0, 1, 0) (0, 2, 0) (0, 3, 0) (1, 2, 2) (1, 3, 3) (2, 3, 6)
8/3/2019 Python_Tips & Tricks
21/45
As you can see, this code iterates over four values of y, and for each ofthose values, iterates over four values of x and then filters and maps.Each list item then, is itself a list of x, y,x * y.
print [(x, y,x * y)for xin (0,1,2,3)for y in (0,1,2,3)if x < y]
#prints [(0, 1, 0), (0, 2, 0), (0, 3, 0), (1, 2, 2), (1, 3, 3), (2, 3, 6)]
8/3/2019 Python_Tips & Tricks
22/45
Reducing a ListFor example, maybe you want find the product of all of the values in alist. You could make a for loop:
Or you could use the built-in function reduce, which accepts afunction that takes two arguments, and a list:
numbers = [1,2,3,4,5]result = 1for number in numbers:
result *= number# result isnow 120
numbers = [1,2,3,4,5]result = reduce(lambda a,b: a*b, numbers)# result isnow 120
8/3/2019 Python_Tips & Tricks
23/45
Iterating over a List: range,xrange and enumerate
Remember (or maybe not) when you programmed in C, and for loopscounted through index numbers instead of elements? You probablyalready know how to replicate this behavior in Python,using range or xrange.
The problem here is that usually you end up needing the list elementsanyways. What's the use of just having the index values? Python has areally awesome built-in function called enumerate that will giveyou both.enumerate-ing a list will return an iteratorof index, value pairs:
strings = ['a', 'b', 'c', 'd', 'e']for indexin xrange(len(strings)):
print index,#prints '0 1 2 3 4'
8/3/2019 Python_Tips & Tricks
24/45
As an added advantage, enumerate is quite a bit cleaner and morereadable than xrange(len()). Because of this, range and xrange are
probably only useful if you need to create a list of values from scratchfor some reason, instead of from an existing list.
strings = ['a', 'b', 'c', 'd', 'e']for index, string in enumerate(strings):
print index, string,#prints '0 a 1 b 2 c 3 d 4 e'
8/3/2019 Python_Tips & Tricks
25/45
Checking a Condition on Anyor Every List Element
Say you want to check to see if any element in a list satisfies acondition (say, it's below 10). Before Python 2.5, you could dosomething like this:
If none of theelements satisfy the condition, the list comprehensionwill create an empty list which evaluates as false. Otherwise, a non-empty list will be created, which evaluates as true. Strictly, you don'tneed to evaluateevery item in the list.
numbers = [1,10,100,1000,10000]if [number for number in numbers if number < 10]:
print 'At least oneelement is over 10# Output: 'Atleastoneelement isover 10'
8/3/2019 Python_Tips & Tricks
26/45
The generator expression only computes these values as they areneeded, and any only requests the values it needs.
Similarly, you can check if every element satisfies a condition. WithoutPython 2.5, you'll have to do something like this:
With Python 2.5, there's of course an easier way. This method worksjust like the any method described above.
numbers = [1,10,100,1000,10000]if any(number < 10 for number in numbers):print 'Success
# Output: 'Success!'
numbers = [1,2,3,4,5,6,7,8,9]if len(numbers) == len([number for number in numbers if number < 10]):
print 'Success!# Output: 'Success!'
numbers = [1,2,3,4,5,6,7,8,9]if all(number < 10 for number in numbers):
print 'Success!
# Output: 'Success!'
8/3/2019 Python_Tips & Tricks
27/45
CombiningMultiple Lists,Item by Item
The built-in zip function can be used, well, to zip lists together. Itreturns a list of tuples, where the nth tuple contains the nth item fromeach of the passed in lists. This might be a case where an example is thebest explanation:
Often you'll use this sort of thing as the iterator a for loop, pulling outall three values at once ('for letter, number, squares in zipped_list').
letters = ['a', 'b', 'c']numbers = [1, 2,3]squares = [1,4, 9]
zipped_list = zip(letters, numbers, squares)
# zipped_listcontains [('a', 1, 1), ('b', 2, 4), ('c', 3, 9)]
8/3/2019 Python_Tips & Tricks
28/45
Advanced Logic With Sets
The most common thing I want to do is to make sure my list isunique. This is easy; I just have to convert it to a set and check if thelength is the same:
Of course, you can convert the set back into a list, but remember thatordering is not preserved.
numbers = [1,2,3,3,4,1]
set(numbers)# returnsset([1,2,3,4])
if len(numbers) == len(set(numbers)):print 'List is unique!
# Inthiscase, doesn'tprintanything
8/3/2019 Python_Tips & Tricks
29/45
Dictionaries
Constructing Dictionaries with KeywordArgumentsThis might be a bit cleaner than a 'regular' dictionary creationdepending on your code; there are less quotes floating around. I use itoften.
dict(a=1, b=2, c=3)
# returns {'a': 1, 'b': 2, 'c': 3}
8/3/2019 Python_Tips & Tricks
30/45
Dicts to Lists
To preserve both keys and values, you can turn a dict into a list oriterator of 2-item tuples by using .items() or .iteritems(). This issomething that you'll probably do a lot, and isn't very exciting:
Lists to DictsYou can reverse the process, turning a list of 2-element lists or tuplesinto a dict:
dictionary = {'a': 1, 'b': 2, 'c': 3}dict_as_list = dictionary.items()
#dict_as_list now contains [('a', 1), ('b', 2), ('c', 3)]
dict_as_list = [['a',1], ['b', 2], ['c',3]]dictionary = dict(dict_as_list, d=4,e=5)# dictionarynow contains {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
8/3/2019 Python_Tips & Tricks
31/45
You can also combine this with the 'keyword arguments method of
creating a dictionary discussed above:
Being able to convert a dict to a list is kind of handy, I guess. But whatreally makes it awesome is the next trick.
dict_as_list = [['a',1], ['b', 2], ['c',3]]dictionary = dict(dict_as_list, d=4,e=5)# dictionarynow contains {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
8/3/2019 Python_Tips & Tricks
32/45
'Dictionary Comprehensions
For example, say I have a dictionary of name:email pairs, and I want tocreate a dictionary of name:is_email_at_a_dot_com pairs:
Damn straight. Of course, you don't have to start and end with a dict,you can throw some lists in there too.
While this is a little less readable than a straight list comprehension,I'd argue it's still better than a massive for loop.
emails = {'Dick': '[email protected]', 'Jane': '[email protected]', 'Stou':'[email protected]'}
email_at_dotcom = dict( [name, '.com' in email] for name,email inemails.iteritems())
# email_at_dotcomnow is {'Dick': True, 'Jane': True, 'Stou': False}
8/3/2019 Python_Tips & Tricks
33/45
Functions
Default Argument Values are Only Evaluated OnceLet's start this section with a warning. Here's a problem that hasconfused many new Python writers, including myself, repeatedly,evenafter I figured out the problem... It's easy to be stupid about this
def function(item, stuff = []):stuff.append(item)print stuff
function(1)#prints '[1]
function(2)#prints '[1,2]' !!!
8/3/2019 Python_Tips & Tricks
34/45
The default value for a function argument is only evaluated once,when the function is defined. Python simply assigns this value to thecorrect variable name when the function is called.The solution: don't use mutable objects as function defaults. Youmight be able to get away with it if you don't modify them, but it's stillnot a good idea.A better way to write the above code would be:
def function(item, stuff = None):if stuff is None:
stuff = []stuff.append(item)print stuff
function(1)#prints '[1]
function(2)#prints '[2]', asexpected
8/3/2019 Python_Tips & Tricks
35/45
Passing keyword and non-keyword Argument
Passing both arbitrary non-keyword arguments and named (non-arbitrary) keyword arguments in one function isseemingly impossible. This is because named keyword argumentsmust be defined before the '*' parameter in the function definition, and
are filled before that parameter is filled. For example, imagine afunction:
We now have a problem: there is no way to specify 'actually_print' as anamed keyword argument while simultaneously providing arbitrarynon-keyword arguments. Both of the following will error:
def do_something(a, b, c, actually_print = True, *args):if actually_print:
print a, b, c, args
8/3/2019 Python_Tips & Tricks
36/45
The only way to pass 'actually_print' in this situation is to pass it as anon-keyword argument:
do_something(1, 2,3,4, 5, actually_print = True)
# actually_print is initiallysetto 4 (see why?) andthen re-set,# causinga TypeError ('gotmultiplevaluesforkeywordargument')
do_something(1, 2,3, actually_print = True,4, 5,6)
# This isnotallowedaskeywordargumentsmaynotprecedenon-keywordarguments. A SyntaxError is raised.
do_something(1, 2,3, True,4, 5,6)
# Result is '1, 2, 3, (4, 5, 6)'
8/3/2019 Python_Tips & Tricks
37/45
Passing a List or Dictionaryas Arguments
Since you can receive arguments as a list or dictionary, it's not terriblysurprising, I suppose, that you can send arguments to a function from alist or dictionary. The syntax is exactly the same as above.
To send a list as non-keyword arguments, just pre pend it with a '*':
And, of course, to send a dictionary as keyword arguments (this isprobably more common), prepend it with '**':
args = [5,2]pow(*args)
# returnspow(5,2), meaning 5^2 which is 25
8/3/2019 Python_Tips & Tricks
38/45
def do_something(actually_do_something=True,
print_a_bunch_of_numbers=False):if actually_do_something:print 'Something has been doneif print_a_bunch_of_numbers:
print range(10)
kwargs = {'actually_do_something': True, 'print_a_bunch_of_numbers': True}do_something(**kwargs)
#prints 'Something hasbeendone', then '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
8/3/2019 Python_Tips & Tricks
39/45
DecoratorsA decorator is a function that wraps another function: the main
function is called and its return value is passed to the decorator. Thedecorator then returns a function that replaces the wrapped function asfar as the rest of the program is concerned.
def decorator1(func):return lambda: func() + 1
def decorator2(func):def print_func():
print func()return print_func
@decorator2
@decorator1def function():
return 41
function()#prints '42'
8/3/2019 Python_Tips & Tricks
40/45
This example does theexact same thing, but more verbosely andwithout decorators:
def decorator1(func):return lambda: func() + 1
def decorator2(func):def print_func():
print func()return print_func
def function():return 41
function = decorator2(decorator1(function))
function()#prints '42'
8/3/2019 Python_Tips & Tricks
41/45
'Switch Statements' using
Dictionaries ofFunctionsFor example, say you're handling keystrokes and you need to call a
different function for each keystroke. Also say you've already definedthese three functions:
def key_1_pressed():
print 'Key 1 Pressed
def key_2_pressed():print 'Key 2 Pressed
def key_3_pressed():
print 'Key 3 Pressed
def unknown_key_pressed():print 'Unknown Key
Pressed'
keycode = 2if keycode == 1:
key_1_pressed()elif keycode == 2:
key_2_pressed()elif number == 3:
key_3_pressed()else:unknown_key_pressed()
#prints 'Key 2 Pressed'
8/3/2019 Python_Tips & Tricks
42/45
But you could also throw all the functions in a dictionary, and keythem to the value you're switching on. You could even check see if the
key exists and run some code if it doesn't:
You can see that this could be a lot cleaner than the elif example for
large numbers of functions.
keycode = 2
functions = {1: key_1_pressed, 2: key_2_pressed,3: key_3_pressed}
functions.get(keycode, unknown_key_pressed)()
8/3/2019 Python_Tips & Tricks
43/45
ClassesPassing 'self'ManuallyMethods are just regular functions that when called from an instanceare passed that instance as the first argument (usually called 'self'). If forsome reason you're not calling the function from an instance, you canalways pass the instance manually as the first argument. For example:
class Class:def a_method(self):
print 'Hey a method'
instance = Class()
instance.a_method()#prints 'Heyamethod', somewhat unsuprisingly. You canalsodo:
Class.a_method(instance)#prints 'Heyamethod'
8/3/2019 Python_Tips & Tricks
44/45
8/3/2019 Python_Tips & Tricks
45/45
Thank You !