The Zen of Python by Tim Peters •Beautiful is better than ugly. •Explicit is better than implicit. •Simple is better than complex. •Complex is better than complicated. •Flat is better than nested. •Sparse is better than dense. •Readability counts. •Special cases aren't special enough to break the rules. •Although practicality beats purity. •Errors should never pass silently. •Unless explicitly silenced. •In the face of ambiguity, refuse the temptation to guess. •There should be one – and preferably only one – obvious way to do it. •Although that way may not be obvious at first unless you're Dutch. •Now is better than never. •Although never is often better than *right* now. •If the implementation is hard to explain, it's a bad idea. •If the implementation is easy to explain, it may be a good idea. •Namespaces are one honking great idea – let's do more of those! Friday, February 18, 2011
Beautiful is better than ugly. • Write programs for human readers • Simple expression syntax • Consistent syntax and behavior Friday, February 18, 2011
Explicit is better than implicit. • Boolean type • No “hidden” loop variables • Use “self” to refer to object inside a method Friday, February 18, 2011
Boolean Values 1 t = True 2 f = False 3 4 if t: 5 print 't is true' 6 7 if not f: 8 print 'f is false' 9 10 a = t or f 11 b = t and f 12 13 print a 14 print b $ python booleans.py t is true f is false True False Friday, February 18, 2011
for loops 1 print 'Numbers:' 2 3 for i in range(5): 4 print i 5 6 print 7 print 'Letters:' 8 9 for c in [ 'a', 'b', 'c' ]: 10 print c $ python for_loop.py Numbers: 0 1 2 3 4 Letters: a b c Friday, February 18, 2011
NumPy Performance 1 a = range(10000000) 2 b = range(10000000) 3 c = [] 4 for i in range(len(a)): 5 c.append(a[i] + b[i]) Standard Python 1 import numpy as np 2 a = np.arange(10000000) 3 b = np.arange(10000000) 4 c = a + b NumPy 5-10 seconds “nearly instantaneous” Friday, February 18, 2011
Flat is better than nested. • Wide variety of modules in standard library • Namespace is flat • No need to use long names: com.company.java.blah.blah Friday, February 18, 2011
Special cases aren’t special enough to break the rules. • Everything is an object • Methods and functions differ by scope • Dynamic typing and runtime attribute lookup • Most “features” in external modules Friday, February 18, 2011
Dynamic Typing 1 class A(object): 2 def do_something(self): 3 print 'in A' 4 5 class B(object): 6 def do_something(self): 7 print 'in B' 8 9 def work_on_obj(c): 10 c.do_something() 11 12 a = A() 13 b = B() 14 15 work_on_obj(a) 16 work_on_obj(b) $ python dynamic_typing.py in A in B Friday, February 18, 2011
Regular Expressions 1 import re 2 3 pattern = 'this' 4 text = 'Does this text match the pattern?' 5 6 match = re.search(pattern, text) 7 8 s = match.start() 9 e = match.end() 10 11 print 'Found :', match.re.pattern 12 print 'In :', match.string 13 print 'Range :', s, '-', e 14 print 'Substring:', text[s:e] $ python using_regex.py Found : this In : Does this text match the pattern? Range : 5 - 9 Substring: this Friday, February 18, 2011
Exceptions and Tracebacks 1 def f(n): 2 if n > 0: 3 return n * f(n-1) 4 return 1 5 6 print f('5') $ python traceback.py Traceback (most recent call last): File ".../traceback.py", line 6, in print f('5') File ".../traceback.py", line 3, in f return n * f(n-1) TypeError: unsupported operand type(s) for -: 'str' and 'int' Friday, February 18, 2011
Raising Exceptions 1 def f(n): 2 if not isinstance(n, int): 3 raise TypeError('n should be an int') 4 if n > 0: 5 return n * f(n-1) 6 return 1 7 8 print f('5') $ python raising.py Traceback (most recent call last): File ".../raising.py", line 8, in print f('5') File ".../raising.py", line 3, in f raise TypeError('n should be an int') TypeError: n should be an int Friday, February 18, 2011
Raising Exceptions 1 def f(n): 2 if not isinstance(n, int): 3 raise TypeError('n should be an int') 4 if n > 0: 5 return n * f(n-1) 6 return 1 7 8 print f('5') $ python raising.py Traceback (most recent call last): File ".../raising.py", line 8, in print f('5') File ".../raising.py", line 3, in f raise TypeError('n should be an int') TypeError: n should be an int Friday, February 18, 2011
Catching Exceptions 1 def f(n): 2 if not isinstance(n, int): 3 raise TypeError('n should be an int') 4 if n > 0: 5 return n * f(n-1) 6 return 1 7 8 try: 9 print f('5') 10 except TypeError, err: 11 print 'Had an error:', err 12 else: 13 print 'No error' 14 finally: 15 print 'Always run' $ python catching.py Had an error: n should be an int Always run Friday, February 18, 2011
In the face of ambiguity, refuse the temptation to guess. • Coerce types only when not surprising • Cannot add strings and numbers • Can multiply them! Friday, February 18, 2011
Although that way may not be obvious at first unless you’re Dutch. • GUI • GTK • KDE • Cocoa • MS Windows • Tk • wxPython • Web • Django • AppEngine • Pyramid • Flask • TurboGears • Pecan Friday, February 18, 2011
References • http://docs.python.org/ • http://www.doughellmann.com/ PyMOTW/ • Learning Python by Mark Lutz • Python Essential Reference by David Beazley • The Python Standard Library by Example by Doug Hellmann • http://us.pycon.org/ Friday, February 18, 2011