Common Python Idioms

Use of programming language idioms makes your code more concise and improves readability. It is often necessary to know the idioms in order to understand what somebody else's code is doing. The examples below illustrate the most common python idioms.

Swapping Values

Swapping values of two variables can be accomplished by a single assignment. For example, to swap values of variables named "a" and "b" use a, b = b, a. The following code snippet illustrates this idiom. Copy/paste it into the python prompt:

a = 1
b = 2
a, b = b, a
print "a is", a, " b is", b

You can do it with as many items as you like:

a, b, c, d = b, c, d, a

maps b into a, c into b, etc. Can you explain why this idiom works? (Hint: think about tuple packing and unpacking.)

Simple Loops

Looping from 0 to n (n itself is excluded) in the increasing order is accomplished by using the "xrange" function inside the "for" statement:

n = 10
for i in xrange(n)
:
    # Do something, for example, print i
    print "i is", i

Here, the "xrange" function is used just like "range" (and it has the same arguments), but it works faster. This is because "xrange" does not build the whole sequence: it just returns elements one at a time when they are needed (technically, "xrange" is a generator).

"xrange" is sometimes useful for building infinite loops. For almost all practical purposes,

for i in xrange(2**31-1):

is equivalent to

while 1:

except that the "for" loop also initializes the "i" variable to the cycle number at the beginning of each cycle. Note that using the "range" function in this situation instead of "xrange" would be a bad idea: "range" would attempt to build a complete sequence with 231 - 1 elements and would probably overflow the memory of your computer.

For people familiar with C/C++: note that pythonic "for" does not work like in C/C++. Instead, its behavior is more similar to the "for_each" function from the C++ standard library. Here is the illustration:

n = 10
for i in xrange(n)
:
    print "i is", i
    i += 1

The snippet above produces identical output to the snippet at the beginning of this subsection because "i" is overwritten at the beginning of each cycle. In C, the effect of incrementing "i" inside the loop body would result in skipping every second printout.

Using Tuples/Lists instead of Simple Classes

In simple cases, you can often avoid writing your own classes by using Python's heterogeneous containers instead. Lists or tuples with small number of elements allow for convenient packing/unpacking on-the-fly. Example:

course_info = ("Computational Physics", "SCI 29", "TTH 14:00 - 15:20")
name, room, time = course_info
print "My", name, "course", "meets", time, "at", room

This technique works especially well if your code makes a good use of built-in functions for container look-up and manipulation. In this case you can save the writing of quite a few methods in a class.

Iterating over Nested Sequences

When you use tuples or lists instead of simple classes, looping over sequences of such tuples can be combined with unpacking:

course_info = (("Computational Physics", "SCI 29", "TTH 14:00 - 15:20"),
            ("Advanced Quantum Mechanics", "SCI 10", "MWF 9:00 - 9:45"))
for (name, room, time) in course_info:
    print "My", name, "course", "meets", time, "at", room

This "for" loop is equivalent to (but slightly faster than)

for info in course_info:
    
name, room, time = info
    print "My", name, "course", "meets", time, "at", room

Iterating over Multiple Sequences

Simultaneous iteration over multiple sequences can be accomplished using the "zip" function. Example:

x_sequence = (1, 2, 3, 4)
y_sequence = (5, 6, 7)
z_sequence = (8, 9)
for x, y, z in zip(x_sequence, y_sequence, z_sequence):
    print "x is", x, " y is", y, " z is", z

Note that the iteration terminates as soon as the shortest sequence runs out of elements.

Default Parameter Values

Be careful while assigning default values to function parameters. In particular, using a mutable object as a default value is usually not the intended thing to do. A typical mistake is initializing a list argument by "[]". Here is a somewhat contrived example which attempts to append the elements of the first argument to the second:

def probably_incorrect_function(a, b=[]):
    for element in a:
        b.append(element)
    return b

Try to call this function more than once:

probably_incorrect_function((1, 2))
probably_incorrect_function((1, 2))

The first time the function returns "[1, 2]" (as intended), wile the second time it returns "[1, 2, 1, 2]". This is because variable "b" always refers to the same object which was created when the python interpreter processed the function definition.

The correct implementation looks like this:

def correct_function(a, b=None):
    if b is None:
        b = []

    for element in a:
        b.append(element)
    return b

Note that the default parameter value is now immutable, and evaluation of the "b is None" statement is very fast: it tests for identity rather than equality.

List Comprehensions

Instead of using the "for" statement to loop over the contents of a list or tuple, simple operations on lists can be performed in one line of code using syntax constructs called "list comprehensions". Here is an example:

x = (0.0, 1.0, 2.0, 3.0, 4.0, 5.0)
y = [z*z for z in x]
print "z is", z, " y is", y

The single line "y = [z*z for z in x]" is equivalent to (but more concise than)

y = []
for z in x:
    y.append(z*z)

One can put a conditional statement into a list comprehension. Example:

y = [z*z for z in x if z > 1]
print "y is", y

In this example the list comprehension statement is equivalent to

y = []

for z in x:
    if z > 1:

        y.append(z*z)

List comprehensions can be conveniently used with functions which take sequences as their arguments. Here, for example, is a sum of squares of integers from 0 to 9, skipping 5:

sum([z*z for z in xrange(10) if z != 5])

One can build really complex comprehensions with multiple "for" and "if" statements inside. Try to avoid those -- they are more difficult to understand than explicit loops.

More Python Idioms