Transfer from http://satyajit.ranjeev.in/2012/05/17/python-a-few-things-to-remember.html
Zen of Python
Learing the culture that surrounds a language bringd you one step closer to being a better programmer. If you haven’t read the Zen of Python yet open a Python prompt and type ‘import this’.For each of the item on the list you can find example here http://artifex.org/~hblanks/talks/2011/pep20_by_example.html
One caught my attention:
Beautiful is better then ugly
Give me a function that takes a list of numbers and return only the even ones,divided by two.
1 | #----------------------------------------------------------------------- |
Remembar the very simple things in Python
- Swaping two variables:
1 | a,b = b, a |
- The step argument in slice operator. For example:
1 | a = [1,2,3,4,5] |
THe special case x[:-1:] is a useful idiom for ‘x reversed’.
1 | >>>z[::-1] |
UPDATE: Do keep in mind x.reverse() reverses the list in place and slices gives you the ability to do this:
1 | >>>x[::-1] |
Don’t use mutables as defaults
1 | def function(x,l=[]): #Don't do this |
UPDATE: I realise I haven’t explained why. I would recommend reading the article by Fredrik Lundh. In short it is by design that this happens. “Default parameter values are always evaluted when, and only when, the “def” statement they belong to is executed;”
Use iteritems rather than items
iteritems uses generators and thus are better whle iterating though very large lists.
1 | d = {1:'1',2:'2',3:'3'} |
This is similar with range and xrange only calls values when requested.
UPDATE: Do note that the iteritems,iterkeys,itervalues are removed from Python3.x. The dict.keys(),dict.items() and ‘dict.values()’ return views instead of lists.
http://docs.python.org/release/3.1.5/whatsnew/3.0.html#views-and-iterators-instead-of-lists
Use isinstance rather than type
Don’t do
1 | if type(s) == type(""): ,,, |
rather:
1 | if isinstance(s, basestring): ... |
For why not to do so: http://stackoverflow.com/a/1549854/504262
Notice I used basestring and not str as you might be trying to check if a nuicode object is a string. For example:
1 | >>> a = u'aaa' |
This is because in Python version below 3.0 there are two string types str and uuicode:
1 | object |
Learn the various collection
Python has various container datatypes which are better alternative to the built-in containers like list and dict for specific cases.
UPDATE: I’m sure most do not use this. Carelessness from my side. A few may consider writing it this way:
1 | freqs = {} |
Some may say a better solution would be:
1 | freqs = {} |
Rether go for the collection type defaultdict
1 | from collections import defaultdict |
Other collections
1 | namedtuple() # factory function for creating tuple subclasses with named fields |
UPDATE: As noted by a few in Hacker News I could have used Counter instead of defaultdict.
1 | >>> from collections import Counter |
When creating classes Python’s magic methods
1 | __eq__(self, other) # Defines behavior for the equality operator, == |
There are serveral others.
Conditional Assignments
1 | x = 3 if (y == 1) else 2 It does exactly what it sounds like:"assign 3 to x if y is 1, otherwise assign 2 to x", You can also chain it if you have something more complicated: |
Though at a certain point, it goes a little too far.
Note that you can use if … else in any expression. For example:
1 | (func1 if y == 1 else func2)(arg1, arg2) |
Here func1 will be called if y is 1 and func2. otherwise. In both cases the corresponding function will be called with arguments arg1 and arg2.
Analogously, the following is also valid:
1 | x = (class1 if y == 1 else class2)(arg1, arg2) |
where class1 and class2 are two classes.
Use the Ellipsis when necessary.
UPDATE: As one commenter mentioned in Hacker News “Using Ellipsis for getting all items is a violation of the only One Way TO Do It principle. The standard notation is [:].” I do agree with him. A better example is given using numpy in stackoverflow:
The ellipsis is used to slice higher-dimensional data structures.
It’s designed to mean at this point. insert as many full slices(:) to extend the multi-dimensional slice to all dimensions.
Example:
1 | >>> from numpy import arrage |
Now, you have a 4-dimensional matrix of order 2x2x2x2. To select all first elements in the 4th dimension, you can use the ellipsis notation
1 | >>> a[...,0].flatten() |
Previous suggestion.
When creating a class you can use __gititem__ to make you class’s object work like a dictionary. Take this class as an example:
1 | class MyCLass(object): |
Because of __getitem__ you will be able to get the value of a in the object x by x['a']. This is probably a know fact.
This object is used to extend the Python slicing.((http://docs.python.org/library/stdtypes.html#bltin-ellipsis-object). Thus if we add a clause:
1 | def __getitem__(self,item): |
We can use x[...] to get list containing all the items.
1 | >>> x = MyCLass(11,24,23,12) |