Python Idioms

last modified: September 9, 2013

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


Loading...