Python Idioms

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


CategoryPython CategoryIdiom


EditText of this page (last edited September 9, 2013) or FindPage with title or text search