Idioms for PythonLanguage.
Expressions
Multiple assignment
def find_best(key):
...
return new_key, value
key, value = find_best(key)
a, b = b, a # swap
Interval test
if 2 < x < 4:
print "x is between 2 and 4."
Set membership test
if val in ('foo','bar'): # or {'foo','bar'},: a set
For performance, store the tuple/set in a variable (whose name could be useful documentation), or just do
if val=='foo' or val=='bar':
Conditional expression
What in CeeLanguage is written
c ? x : y
is in Python (see http://www.python.org/peps/pep-0308.html for history)
x if c else y # note order
In Python <2.5, use (if you must) one of
c and x or y # incorrectly returns y if x is (any kind of) false
(c and [x] or [y])[0] # reliable, but ugly and churns objects
(x, y)[not c] # always evaluates both
(y, x)[c] # only if c is really a bool (or otherwise 0 or 1)
Loops
Iterating over a list
for f in foo:
print f * bar
not
for i in range(len(foo)):
print foo[i] * bar
Iterating over the lines in a file
with open('foo') as f: # automatically close f even on exception
for line in f:
...
not
f=file('foo') # synonym for open; see http://mail.python.org/pipermail/python-dev/2004-July/045921.html
for line in f.readlines(): # store whole file in memory
...
In CPython, the "with" is not so necessary, as dropping the last reference to f will close the file (but that can happen later than you think in case of exceptions).
Repeat-until loop
while True:
...
if test: break
...
Functions
Properties
Rather than getters and setters, simply write
class MyObj(object):
def __init__(self): self.foo=0
obj=MyObj()
obj.foo=4
You can later make foo a property if logic is necessary:
class MyObj(object):
def __init__(self): self._foo=1 # oops, it has to be odd now
@property # this is a "decorator"
def foo(self): return self._foo
@foo.setter
def foo(self,x): self._foo=x-x%2+1 # round up to next odd number
obj=MyObj()
obj.foo=4 # now assigns 5
Dispatch tables
disp = { 0: f0, 1: f1, 2: f2, 3: f3 }, # dictionary of functions
x=disp[n](...) # choose and call
not
if n==0: x=f0(...)
elif n==1: x=f1(...)
elif n==2: x=f2(...)
elif n==3: x=f3(...)
else: raise KeyError(n) # for symmetry with the above
(Python has no SwitchStatement.)
Optimization
Avoid a defensive copy
If a function stores a mutable argument, you might want to copy it to avoid action at a distance:
class A(object):
def f(self,l): self.list=l[:]
If it's common for the call to look like
a=A()
a.f([1,2,3]) # no other reference to this list anyway
(but with a large list that shouldn't be needlessly copied) you can (in CPython) optimize away the copy:
import sys
class A(object):
def f(self,l):
if sys.getrefcount(l)>3: l=l[:]
self.list=l
The three allowed references are l itself, and its presence in the argument lists of f() and of getrefcount().
(This occurred to me just before writing this on June 20 2013; thoughts welcome. -- DavisHerring)
Others
The PythonCookbook: ISBN: 0596001673 and http://aspn.activestate.com/ASPN/Cookbook/Python/, parts of which are written/edited by the illustrious Alex Martelli.
From Monty Python and the Holy Grail:
LAUNCELOT: No, no, sweet Concorde! Stay here! I will send help as soon as I have accomplished a daring and heroic rescue in my own particular... [sigh] CONCORDE: Idiom, sir? LAUNCELOT: Idiom!
See also http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html