Python programming language
index

Note: This was written in 2004, has not been (never will be) updated for Python 3.


basic syntax

stmt:                           # trailing colon introduces 
    stmt2                       # an indented statement or clause 

#                               # comment 

\                               # line continuation 

;                               # statement separator (like C) 
if cash > price: Eggs(); Spam() # we eat both if we've enuff money 

True False                      # note spelling (Python 2.3) 

"abc"                           # strings can be enclosed 
'abc'                           # in single or double quotes 

s = 'abc'
s[0] = 'A'                      # wrong: strings are immutable 

(n,n,...)                       # tuple 
n,n,...                         # tuple 
t = (1, 2, 3)                   # named tuple variable 
n = t[0]                        # access tuple element 

t = ('math',101)                # create named tuple 
(course,num) = t                # unpack tuple 

[n,n,...]                       # list 
list = [ 'a', 'b', 'c' ]        # list variable 
list[1]                         # access element 

list = [ 'eggs', 12 ]           # heterogenous lists are supported by Python 
                                # but using tuples as elements may be better 

d = {'vorlon':0, 'shadow':1}    # create dictionary 
d['vorlon']                     # access by key 

None                            # NULL 

not                             # logical/boolean not returns True/False 

# Logical/boolean and/or 
# For 'X or Y', returns X if it's true, else Y 
# For 'X and Y', returns X if it's false, else Y 
# Both return an object, not true/false nor 0/1! 
a = 0; b = 2; plan = a or b     # plan = 2 (not 1 as one might expect)
i = 0; L = []; z = i or L       # z = [] (z = L) 
i = 0; L = []; z = L or i       # z = 0  (z = i) 

& | ~                           # bitwise 

== != < > <= >=                 # equality, relational 

is                              # object identity 
is not

**                              # power (x^y) 

//                              # floor division (truncates to integer) 

pass                            # NOP 

*                               # multiple meanings: 
str = 2 * 'abc'                 # repeats a string: 'abcabc' 
x = (1, 2, 3)                   # unpacks a tuple into individual values 
func( *x )                      # pass 3 separate args rather than a tuple 

+= -= *= etc                    # shorthand like C 

if <cond>:                      # conditional 
[elif <cond>:]
[else:]

while <cond>:                   # while loop 
    [break]                     # break out of looping 
    [continue]                  # iterate to top of loop 
[else:]                         # 'else' clause will execute when condition becomes false. 
                                # To be exact, 'else' will execute unless 'break' was executed. 

for item in sequence:
    if item == sought:
        break
else:                           # This is Pythonic way of saying "if item not found". 
    print item, 'not found'     # 'else' clause will execute unless 'break' was executed. 

return                          # implicitly returns None 
return (res1,res2)              # a tuple can be used to return multiple values 

try:                            # except clause executed if exception matches 
[except [exception[,value]]]:   # omitted name matches any exception 
else:                           # else clause executed if no exception 

def func( arg1, arg2 = 10 )     # second arg has a default 
def func( *arg )                # arg is a tuple (arbitrary number of arguments) 
func( (123, 456, 789) )         # arg = ( 123, 456, 789 ) 
foo( name='eggs', age='12' )    # args can be specified by name 
def func( arg1, **arg2 )        # final arg is a dictionary 

float(123) float('123.0')       # convert integer/string to float 
str(123)                        # convert to string (stringify) 
`123`                           # convert to string (stringify) (deprecated) 
int(1.5)                        # convert to integer (truncate) 
bool(x)                         # convert to boolean 
hex(15)                         # convert to string in hex format 
int('101',2)                    # convert to int from binary number in string 

# A list comprehension is a shorthand with two usual forms: 
# [ x for x in seq ] 
# [ x for x in seq if expr ] 
# A list comprehension creates a new list by appending 'x' 
# on every iteration of 'for x in seq'. 
# If an optional 'if' clause is written, 'x' is only appended 
# if 'if' clause evaluates to true. 
list = [ 1, 2, 3, 4, 5, 6 ]
result = [ 2*x for x in list]              # new list whose elements are double 
result = [ x for x in list if x % 2 == 0 ] # new list with even values 

# lamba creates an anonymous function.  Unlike 'def', 
# formal args aren't parenthesized.  A lambda is limited to 
# being an expression and its result is implicitly returned. 
sum = lambda a, b: a + b
x = sum(10,20)

# Class attributes have similarities to C++ static members. 
# Inside a class block, they're set using their unqualified names. 
# But inside a method, class attributes require class-qualified names 
# to distinguish them from method local vars and instance attributes. 
class Class:
    msCnt = 0         # right 
    Class.msCnt = 0   # wrong (class name isn't valid yet) 

    def __init__( self ):
        print msCnt        # wrong (non-existent local var) 
        print s.msCnt      # technically wrong (will work): class attribute confused as instance attribute 
        print Class.msCnt  # right 
        self.msCnt += 1    # wrong: changes this instance's attribute, not class attribute 
        Class.msCnt += 1   # right 

common phrases, expressions, idioms

person = 'Methuselah'           # counterpart to C printf() 
age = 969
print '%s lived %d years.' % (person, age)

if 90 <= percent <= 100:        # between test 

x or y                          # result is x if x is True or y 
x and y                         # result is y if x is True or x 
return x or y or None           # return x if it's True, or y if it's True, or None 

a, b = b, a                     # swap 
a, b = 0, 2                     # Since boolean 'or' returns first object that is true, 
plan = a or b                   # it can be written as a terse idiom instead of if/else. 
if a:                           # Result is plan = 2 (not plan = 1) 
    plan = a
else:
    plan = b

t = ()                          # empty tuple 
t = 'a',                        # trailing comma necessary to assign tuple 

t = ('abc',1)                   # to modify a tuple: 
t[1] = 2                        # wrong 
t = (t[0],2)                    # right (by reassignment) 

tup = (64, 'bits')              # comparing objects of utterly different types is allowed 
if tup[0] == tup[1]:            # which may be useful with heterogenous sequences 

list = []                       # to append to a list: 
list[0] = 'a'                   # wrong, would throw IndexError 
list.append( 'a' )              # right 

list = [None] * 256             # pre-allocate 256 elements (None repeated 256 times) 
list[255] = 1                   # ok 

list[:]                         # select entire sequence 
str[:]                          # don't write list[0:-1] (pitfalls) 

for i in xrange(10): print i    # iterate thru {0,..,9} 
                                # avoid range() which has a pitfall 

for element in [1, 3, 7, 12]:   # iterate thru a LIST 
for element in (1, 3, 7, 12):   # iterate thru a TUPLE 

for line in open('myfile.txt'): # print lines of a file 
    print line

x in seq, x not in seq          # True/False if x is/not in sequence 

word = 'abc' + 'def'            # catenate strings 

# Positive indexes are zero-based. 
# Negative indexes are allowed. 
data[0]                         # first elem 
data[-1]                        # last elem 

# Slicing applies to a sequence (strings, lists). 
# Lower bound is inclusive, upper bound is exclusive. 
data[:2]                        # first two elems 
data[2:]                        # all elems following first two 
data[-2:]                       # last two elems 
data[:-2]                       # all elems excluding last two 
data[::-1]                      # reverses order (Python 2.3)

del list[i]                     # delete ith element 

aString = 'abc'                 # to unpack: 
aList   = [1, 2, 3]             
aTuple  = 'Jane', 28, 'CS'      
first, second, third = aString  # unpack string 
first, second, third = aList    # unpack list 
first, second, third = aTuple   # unpack tuple 

class Object:                   # declaring a class 
    def foo( self ):            # self is always first arg of class methods 

obj.data                        # accessing a class member 

class Derived(Object)           # deriving a class 
class Derived2(Base1,Base2)     # multiple inheritance 

class Object:                   # __init__() is always name 
        def __init__(self):     # of every constructor in Python 

obj = Object()                  # instantiating an object from a class 

class Object:                   # Class members can be created by constructor. 
    def __init__(self):         # .data is created dynamically in this case. 
        self.data = GetData()   # Note that 'self.' is necessary. 

class Base:                     # Programmer must explicitly call 
    def __init__(self):         # base constructors in Python. 
    ...
class Derived:
    def __init__(self):
        Base.__init__(self)

class MyClass:                  # Python nearest counterpart to C++'s private 
    def __init__(self):         # is to prepend two underscores to a member. 
        self.__private = 1

# iter*() returns iterators.  Pitfall: Loop must not modify dictionary. 
for k in d.iterkeys():          # iterate thru keys in dictionary (by iterator object) 
for v in d.itervalues():        # iterate thru values in dictionary (by iterator object) 
for (k,v) in d.iteritems():     # iterate thru pairs in dictionary (by iterator object) 
# values(),keys(),items() return lists derived from dictionary. 
for k in d.keys():              # iterate thru list of keys from dictionary 
    if k == deleted:
        del d[k]                # ok: iteration is thru list rather than dictionary 
for v in d.values():            # iterate thru list of values from dictionary 
for (k,v) in d.items():         # iterate thru list of pairs from dictionary 

i = 123                         # test type of an object 
if isinstance(i,int):
>>> type(i)
<type 'int'>

def Func():                     # This isn't a dangling reference. 
    x = 123                     # name 'x' is destroyed when function returns 
    return x                    # but object referenced by 'x' is returned. 
y = Func()

pitfalls, traps, quirks

# Pitfall: A silent NOP!  ++ is two unary positive operators in Python! 
++x

# Pitfall: Use xrange() instead of range(). 
# Same syntax.  xrange() creates an iterator.  range() creates a list. 
for i in range(10*1024*1024): #  wrong: that's why you ran out of swap-space 

# Pitfall: Trying to modify a function arg by assignment 
# is wrong because a function arg is a local name. 
Mangle(list)         # wrong: this won't be an in-place modification 
def Mangle(list):
    list = list[1:]  # wrong: creates a new list and assigns to a local name 

list = Mangle(list)  # right 
def Mangle(list):    
    list = list[1:]
    return list

list = Mangle(list)  # better 
def Mangle(list):    
    del list[0]
    return list

# Pitfall: Modifying a sequence by a loop: 
list = [ 0, 0, 0 ]
for item in list: # wrong: changes item not list[] 
    item = 1      # item is a temporary object 
for i in xrange( len(list) ):
    list[i] = 1   # right 

# Pitfall: Tuple elements cannot be re-assigned. 
# But a tuple as a whole can be. 
t = (1, 2)
t[1] = 3        # wrong 
t = (t[0], 3)   # right 

# Pitfall: For basic types, assignment effectively creates a copy. 
# But for all other objects, assignment creates a reference!! 
# Assignment to basic type: 
x = 1
y = x
x = 2  # results: x = 2, y = 1 (as you would expect) 
# Assignment to non-basic type: 
list = [ 1, 2 ]
listSaved = list
list[0] = 3          # wrong: list[0] = listSaved[0] = 3 
listSaved = list[:]  # right (shallow copy) 

# Pitfall: shallow copy vs. deep copy. 
# A shallow copy of a list only copies 
# first-level elements. 
# If a list contains nested lists, 
# a deep copy is necessary to make copies 
# of nested lists. 
listSaved = list[:]              # shallow copy 
import copy
listSaved = copy.deepcopy(list)  # deep copy 

# Pitfall: deleting a list element. 
list = [ 1, 2, 3 ]
list[0] = []   # wrong, turns list[0] into empty list: [ [], 2, 3 ]  
del list[0]    # right 

# Pitfall: del removes elements from a list but 
# doesn't really delete elements themselves. 
obj1 = MyClass()
obj2 = MyClass()
list = [ obj1, obj2 ]
del list[:]       # list emptied but obj1, obj2 survive 

# Pitfall: To avoid slice pitfalls: 
# Remember that lower bound is inclusive but upper is exclusive. 
# Think of indices as pointing between characters, 
# with left edge of first character numbered 0. 
# Right edge of element n is at index n (upper bound). 
# 
#  +---+---+---+---+---+ 
#  | A | B | C | D | E | 
#  +---+---+---+---+---+ 
#  0   1   2   3   4   5 
# -5  -4  -3  -2  -1     
# 
# For example: 
# s = 'ABCDE' 
# s[0:4] is 'ABCD' (not 'ABCDE') 
# s[-5:-1] is 'ABCD' also (s[-1:-5] would be wrong) 

# Pitfall: Intent is to remove all elements from a list: 
del list[0:-1]    # wrong, removes all elements except last 
del list[:]       # right 

# Pitfall: invoking base constructors. 
# Python doesn't call __init__() methods of base (ancestor) classes. 
# Programmer must explicitly call ancestor __init__() methods 
# or call super(). 

# Pitfall: Use 'global' to assign a global variable 
# by a function (similar to PHP) to avoid UnboundLocalError. 
gx = 0
def Func(x):
    global gx
    gx = gx + x
    return
def Func2():
    gx = 1    # wrong: creates gx in local scope (need global gx) 

# Pitfall: Built-in names can be reassigned by mistake. 
open = True   # wrong 

tricks, recipes


Trick: Portable way to locate python interpreter 

#!/usr/bin/env python


Trick: Abbreviating self 

# Writing 'self' is only a convention: it can be written as 's' for brevity. 

class Class:
    def __init__( s ):


Trick: static local variable 

# Functions can be given attributes which can serve as static local variables. 
def func( input ):
    if input == func.lastInput:    # avoid recomputing same input 
        return func.lastResult
func.lastInput  = None
func.lastResult = None


Trick: Counterpart to C++ static class member 

# Python class attributes can be used (with care) 
# as counterparts to C++ static class members. 
# By contrast, data attributes are per-instance variables. 
# A class attribute must be assigned using name of class. 
# Assigning a class attribute using name of an instance is a pitfall 
# as it will create a per-instance variable that'll override class variable. 
class MyClass:
    shared = 1
c1 = MyClass()
c2 = MyClass()
c1.shared = 2       # wrong: affects only c1 (c2.shared is still 1)
MyClass.shared = 2  # right: affects all instances of MyClass 
                    # (except those with an overriding per-instance variable) 


Trick: Constant (read-only) variables 

# By Alex Martelli http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207 
# Put in const.py...: 
class _const:
    class ConstError(TypeError): pass
    def __setattr__(self,name,value):
        if self.__dict__.has_key(name):
            raise self.ConstError, 'Can not rebind const(%s)' % name
        self.__dict__[name] = value
import sys
sys.modules[__name__] = _const()
# that's all -- now any client-code can 
import const
# and bind an attribute ONCE: 
const.magic = 23
# but NOT re-bind it: 
const.magic = 88      # raises const.ConstError 
# you may also want to add obvious __delattr__ 

code snippets

# Dynamically create a list of lists (multi-dimensional list). 
# This snippet is from pyspaceinvaders: it has a list of 
# alien columns in which each column is a list of alien objects. 
alienColCnt = 10
alienColumns = []
for col in range(alienColCnt):
    alienColumns.append( [] )         # add list as an element (nested list) 
    alien = Alien()                   # new Alien object 
    alienColumns[col].append( alien ) # add to 2nd-level list 

# Prune invalid objects in a list. 
# Requires: Objects in elements have a .valid member. 
#           List is flat (no nested sequences). 
# Deleting items while iterating thru a list 
# is an error in Python, so a copy is used. 
def PruneList( list ):
    tmp = list[:] # copy list (shallow copy) 
    i = -1
    for obj in tmp:
        i += 1
        if not obj.valid:
            del list[i]
            i -= 1
    return

# Prune invalid objects in a list of lists (2D list). 
# Requires: Objects in elements have a .valid member. 
#           List must not be deeper than 2 levels. 
def PruneListList( listList ):
    tmpListList = listList[:] # copy list (shallow copy) 
    i = -1
    for list2 in tmpListList: # for each 2nd-level list 
        i += 1
        j = -1
        for obj in list2:
            j += 1
            if not obj.valid:
                del listList[i][j]
                j -= 1
    return

# Iterate over a list of tuples. 
tupleList = [ ('math',101), ('chemistry',102) ]
for t in tupleList:
    print 'class %s %d' % t
for (course,num) in tupleList: # alternative 
    print 'class %s %d' % (course,num)

# ------------------------------------ 
# Printing a user-defined class/object 
# ------------------------------------ 

class MyClass:
    def __init__(self,n):
        self.val = n
    def __str__(self):
        return 'val = %d' % self.val
obj = MyClass(12)
print obj

# Remove duplicates from a list. 
def Unique( l ):
    d = {}
    for k in l:
        d[k] = 1
    return d.keys()

commentary/opinion

positive:
Python code is very sleek and readable because of indentation. Python offers a large set of libraries.

negative:
After Python 3 broke compatibility with existing Python 2 programs by many "enhancements" that seemed whimsical or academic, this author began avoiding Python.