by leonardo maffi
Version 1.12, May 14 2008
Sometimes even good programmers at their first tries of Python use less than optimal solutions and language constructs. In the years Python has accumulated few redundancies and few warts (and some of them will be removed with Python 3.0), but it's a generally clean language still, so with a page like this you can avoid the most common ones. This page hopes to be really simple and short enough, you can find explanations online elsewhere.
For some things I may be wrong, but this page comes from some experience, so when you don't agree with me, I suggest you to go look for the truth inside many newsgroups and Web pages, just don't assume you are right. If you find I am wrong, or you have questions or comments my email address can be found in my Home Page, I'll glady improve this page and learn from my mistakes.
[Go back to the index (email in the Home Page)]
|
Bad
|
Good
|
| x=5 print x,x*x+1 |
x
= 5 print x, x*x + 1 |
| def Function ( x ): ... | def function(x): ... |
| class fooclass: ... | class Fooclass(object): ... |
| d = dict() | frequences = {} |
| list
= [1, 2, 3] dict = {'alpha': 0x1234} sum = x + y |
# Do not shadow builtin names values = [1, 2, 3] symbol_address = {'alpha': 0x1234} tot = x + y |
| if ( (x==8) and (y>5) ): ... | if x == 8 and y > 5: ... |
| while (x<5): ... | while x < 5: ... |
| "some
string" and 'some string' and ""some string""" and '''some string''' are the same string. |
|
| mapping = { 5 :"5", 6:"6" } | mapping = {5 : "5", 6 : "6"} |
| mapping
= {5 : "5", 6 : "6"} if mapping.has_key(6): ... |
mapping
= {5 : "5", 6 : "6"} if 6 in mapping: ... |
| def function( x, l = [] ): ... | #
Generally don't use mutables as a default def function(x, l=None): ... if l is None: l = [] |
| if x == None: ... | if x is None: ... |
| x
= 1 if z > 5: var1 = 55 |
#
Always use 4 spaces as indent # (Or always a Tab, but it's less good) x = 1 if z > 5: var1 = 55 |
| mapping
= {5 : "5", 6 : "6"} for key, val in mapping.items(): ... for key in mapping.keys(): ... |
#
Use iter* methods when possible mapping = {5 : "5", 6 : "6"} for key, val in mapping.iteritems(): ... for key in mapping: ... |
| for i in range(10, 2000): ... | for i in xrange(10, 2000): ... |
| #
Use this to denote the code that has to # run when a module is executed and not # imported: if __name__ == '__main__': |
|
| #
Python profiler: python -m profile -o stats myscript.py import pstats p = pstats.Stats('stats'); p.sort_stats('time').print_stats(15) |
|
| For
source code with not 7-bit ASCII add this on top: # coding: latin |
|
| al
= [1, 2, 3] for i in xrange(len(al)-1, -1, -1): del al[i] |
al
= [1, 2, 3] del al[:] # But often if speed isn't critical you # can just use: al = [] |
| repeat xxx until yyy |
#
Equals to: while True xxx if yyy: break |
| #
To add a zip file containing modules # to the search path: sys.path.append("some.zip") |
|
| a
= 5 b = 6 a = aux a = b b = aux |
a
= 5 b = 6 a, b = b, a # Swap |
| if x < 10 and x > 2: ... | if 2 < x < 10: ... |
| a
= 5 b = 5 c = 5 |
a = b = c = 5 |
| if
x == 1: y = fun1(x) else if x == 2: y = fun2(x) else if x == 3: y = fun3(x) else: y = None |
if
x == 1: y = fun1(x) elif x == 2: y = fun2(x) elif x == 3: y = fun3(x) else: y = None # Sometimes it's even better to use a dict: funs = {1:fun1, 2:fun2, 3:fun3} y = funs.get(x, lambda x:None)(x) |
| mapping
= {5 : "5", 6 : "6"} for key in mapping.iterkeys(): ... |
mapping
= {5 : "5", 6 : "6"} for key in mapping: ... |
| al
= [1, 2, 3] for i in xrange(len(al)): print al[i] |
al
= [1, 2, 3] for el in al: print el |
| al
= [1, 2, 3] for i in xrange(len(al)-1, -1, -1): print al[i] |
al
= [1, 2, 3] for el in reversed(al): print el |
| class
Test(object): def __init__(I, x): ... |
class
Test(object): def __init__(self, x): ... |
| #
Compute the sum of the ... def sum_of(x, y, z): ... |
def sum_of(x, y, z): ... """Compute the sum of the ...""" |
| from
operator import add sl = ["ab", "cd", "ef"] all = "" for s in sl: all += s # Or: sl = ["ab", "cd", "ef"] all = reduce(lambda x,y: x+y, sl, "") |
sl
= ["ab", "cd", "ef"] all = "".join(sl) |
| a
= "this isn't a word, right?" a = a.replace("'", " ") a = a.replace(".", " ") a = a.replace("?", " ") a = a.replace(",", "") |
from
string import maketrans tab = maketrans("'.?", " ") a = "this isn't a word, right." afilt = a.translate(tab, ",") |
| values = ["stop",0,0] | values = ["stop", 0, 0] |
| def
mul(x, y): return x*y l = [2, 3] print apply(mul, l) |
def
mul(x, y): return x*y l = [2, 3] print mul(*l) |
| vals
= [2, 3, -5, 0] result = [] for el in vals: if el > 0: result.append(el * el) |
vals
= [2, 3, -5, 0] result = [el * el for el in vals if el > 0] |
| l
= [0] * 4 m = [l] * 4 m[1][1] = 5 print m |
#
One correct way to create a matrix: m = [[0] * 4 for _ in xrange(4)] m[1][1] = 5 print m |
| a
= 1 print a / 2, a / float(2) |
#
A kind of alternative: from __future__ import division a = 1 print a // 2, a / 2 |
| class
Foo(object): def __init__(self, x, y, z): self.x_public = x self.y_private = y self.z_veryprivate = z def getx(self): return self.x_public print Foo(1, 2, 3).getx() |
# Generally getters
and setters are not used. |
| finder
= re.compile("^\s*([\[\]])\s*([-+]?\d+) \s*,\s*([-+]?\d+)\s*([\[\]])\s*$") |
finder
= re.compile(r""" ^ \s* # start at beginning+ opt spaces ( [\[\]] ) # Group 1: opening bracket \s* # optional spaces ( [-+]? \d+ ) # Group 2: first number \s* , \s* # opt spaces+ comma+ opt spaces ( [-+]? \d+ ) # Group 3: second number \s* # opt spaces ( [\[\]] ) # Group 4: closing bracket \s* $ # opt spaces+ end at the end """, flags=re.VERBOSE) |
| def
function(data): """A comment""" ...implementation... |
#
Use doctests (or module tests): def function(data): """A comment >>>
function() if __name__ == "__main__": |
|
x = (1, 2, 6, 55, 63, 96, 125, 256, \ 301, 456, 958, 1256, \ 1359, 2568, 3597) |
x
= (1, 2, 6, 55, 63, 96, 125, 256, 301, 456, 958, 1256, 1359, 2568, 3597) # Too much long lines must be broken with \ # but \ isn't necessary inside () [] {} |
| from
Tkinter import * from mymodule import * |
import
Tkinter as tk from mymodule import fun1, fun2, Class1 |
| import
psyco psyco.bind(myfun1) a = [3.56, 2.12] |
try: import psyco # Psyco classes may be very useful from psyco.classes import __metaclass__ psyco.bind(myfun1) except ImportError: pass # Using psyco array.array of double and # signed long become very fast import array a = array.array("d", [3.56, 2.12]) |
| #
to print strings without spaces between: from sys import stdout stdout.write(string1) stdout.write(string2) |
|
| words = ['me', 'do' 'bye', 'taz', 'foo', 'bar'] | words = 'me do bye taz foo bar'.split() |
| #
sorting on the second item of the tuple # try to remove the i index from the temporary tuples lp = [(5J,"b"),(2J,"c"),(3+1J,"a"),(1+2J,"a")] lp2 = [(c, i, n) for i,(n, c) in enumerate(lp)] lp2.sort() print [(n, c) for (c, i, n) in lp2] |
from
operator import itemgetter lp = [(5J, "b"), (2J, "c"), (3+1J, "a"), (1+2J, "a")] print sorted(lp, key=itemgetter(1)) |
| vals
= [5, 7 ,8] tot = -2.0 for v in vals: tot += v |
vals
= [5, 7 ,8] tot = sum(vals, -2.0) |
| ll
= [[1, 2, 3], [4], [5, 6]] print sum(ll, []) |
data
= [[1, 2, 3], [4], [5, 6]] result = [] for sublist in data: result.extend(sublist) # Or even, for max speed from itertools import imap data = [[1, 2, 3], [4], [5, 6] result = [None] * sum(imap(len, data)) pos = 0 for sublist in data: lensl = len(sublist) result[pos : pos+lensl] = sublist pos += lensl |
| print
"%s %s" % (string1, string2) print '"' + chr(c) + '":', freq[c] |
print
string1, string2 print '"%c": %d' % (c, freq[c]) |
| [' ', c][c.isalpha()] | #
For Python V.2.5+: (c if c.isalpha() else ' ') |
| #
How to invert string, lists, etc. alist[::-1] astring[::-1] |
|
|
# To negate (inplace) each second # element of alist: result = [] for (i, v) in enumerate(alist): # faster than i % 2 if i & 1 == 0: result.append(v) else: result.append(-v) alist[:] = result |
from operator import neg alist[1::2] = map(neg, alist[1::2]) # Or a bit slower but easier to read: alist[1::2] = [-el for el in alist[1::2]] |
| #
To shallow copy a list or dict: # (tuples don't need to be copied) newlist = list(alist) newdict = dict(adict) # Old syntax to copy a list: newlist = list[:] |
|
| import
sys sys.exit() |
#
To stop a console program: raise SystemExit |
| if
type(s) == type(""): ... if type(seq) == list or \ type(seq) == tuple: ... |
if
isinstance(s, basestring): ... if isinstance(seq, (list, tuple)): ... # Or even: if hasattr(seq, "__getitem__"): ... |
| #
All uppercase for variables that don't change CONSTANT1 = 10 ANOTHER_CONSTANT = 20 var1 = 30 another_variable = 40 |
|
| name1
= 5; name2 = 20; print name2 a = 1 b = 2 c = 3 |
name1
= 5 name2 = 20 print name2 a, b, c = 1, 2, 3 |
| prima
= 10 rossa = 20 léger = 30 |
#
English only for names: first = 10 red = 20 light = 30 |
| __del__
method of classes is usually undefined. |
|
| try: fin = file("absent_file.txt") except: ... try: something() except: ... |
#
Always specify what exception to catch try: fin = file("absent_file.txt") except IOError: ... try: something() except someException: ... |
| except ImportError, IOError: ... | except (ImportError, IOError): ... |
| bytes
= array.array('B', [0] * nbytes) # Or: from itertools import repeat bytes = array.array('B', repeat(0, nbytes)) |
bytes = array.array('B', [0]) * nbytes |
| freqs
= {} for c in "abracadabra": try: freqs[c] += 1 except: freqs[c] = 1 |
freqs
= {} for c in "abracadabra": if c in freqs: freqs[c] += 1 else: freqs[c] = 1 # Or even better on Python 2.5: from collections import defaultdict freqs = defaultdict(int) for c in "abracadabra": freqs[c] += 1 |
|
someitems = set([1,
2, 3]) |
someitems
= set([1, 2, 3]) somemap = {1:2, 3:4, 5:6} print iter(someitems).next() print iter(somemap).next() |
Thank to Mark Dufour for fixing few errors, and Francesco Brasini for another bug spotted.
See PEP 8 too for more style guides for Python code: http://www.python.org/dev/peps/pep-0008/
[Go back to the index (email in the Home Page)]