2. The Zen of Python
by Tim Peters
• Beautiful is better than ugly. • There should be one – and
• Explicit is better than implicit. preferably only one – obvious way
• Simple is better than complex. to do it.
• Complex is better than • Although that way may not be
complicated. obvious at first unless you're
• Flat is better than nested. Dutch.
• Sparse is better than dense. • Now is better than never.
• Readability counts. • Although never is often better than
• Special cases aren't special *right* now.
enough to break the rules. • If the implementation is hard to
• Although practicality beats purity. explain, it's a bad idea.
• Errors should never pass silently. • If the implementation is easy to
• Unless explicitly silenced. explain, it may be a good idea.
• In the face of ambiguity, refuse the • Namespaces are one honking
temptation to guess. great idea – let's do more of those!
3. Beautiful is better
than ugly.
• Write programs for human
readers
• Simple expression syntax
• Consistent syntax and
behavior
4. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
5. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
6. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
7. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
8. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
9. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
10. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
11. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
12. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
13. Simple Expressions
1 i = 5 + 5 13
2 14 t = ('a', 1, vals, None)
3 s = 'literal string' 15 t[1]
4 16
5 m = """multi-line 17 d = { 'a':'a value',
6 string 18 'b':'b value',
7 """ 19 }
8 20 d['a']
9 us = u'üñîçø∂é string' 21
10 22 if a or b:
11 vals = [ 1, 3, 5, 7, ] 23 do_something()
12 vals[0] 24
14. Explicit is better than
implicit.
• Boolean type
• No “hidden” loop variables
• Use “self” to refer to object
inside a method
15. Boolean Values
1 t = True
2 f = False
3
4 if t:
5 print 't is true'
$ python booleans.py
6
t is true
7 if not f:
f is false
8 print 'f is false'
True
9
False
10 a = t or f
11 b = t and f
12
13 print a
14 print b
16. for loops
$ python for_loop.py
1 print 'Numbers:' Numbers:
2 0
3 for i in range(5): 1
4 print i 2
5 3
6 print 4
7 print 'Letters:'
8 Letters:
9 for c in [ 'a', 'b', 'c' ]: a
10 print c b
c
17. Defining a Class
1 class MyClass(object):
2 """Class documentation.
3 """
4
5 def __init__(self, arg1, arg2):
6 self.attr1 = arg1
7 self.attr2 = arg2
8
9 def do_something(self):
10 """Does some work and returns a value.
11 """
12 return self.attr1 * self.attr2
13
14 obj = MyClass(1, 2)
15 print obj.do_something()
18. Defining a Class
1 class MyClass(object):
2 """Class documentation.
3 """
4
5 def __init__(self, arg1, arg2):
6 self.attr1 = arg1
7 self.attr2 = arg2
8
9 def do_something(self):
10 """Does some work and returns a value.
11 """
12 return self.attr1 * self.attr2
13
14 obj = MyClass(1, 2)
15 print obj.do_something()
19. Defining a Class
1 class MyClass(object):
2 """Class documentation.
3 """
4
5 def __init__(self, arg1, arg2):
6 self.attr1 = arg1
7 self.attr2 = arg2
8
9 def do_something(self):
10 """Does some work and returns a value.
11 """
12 return self.attr1 * self.attr2
13
14 obj = MyClass(1, 2)
15 print obj.do_something()
20. Defining a Class
1 class MyClass(object):
2 """Class documentation.
3 """
4
5 def __init__(self, arg1, arg2):
6 self.attr1 = arg1
7 self.attr2 = arg2
8
9 def do_something(self):
10 """Does some work and returns a value.
11 """
12 return self.attr1 * self.attr2
13
14 obj = MyClass(1, 2)
15 print obj.do_something()
21. Defining a Class
1 class MyClass(object):
2 """Class documentation.
3 """
4
5 def __init__(self, arg1, arg2):
6 self.attr1 = arg1
7 self.attr2 = arg2
8
9 def do_something(self):
10 """Does some work and returns a value.
11 """
12 return self.attr1 * self.attr2
13
14 obj = MyClass(1, 2)
15 print obj.do_something()
22. Simple is better than
complex.
• Garbage collection
• print statement
• Interactive interpreter for
experimentation
28. NumPy Performance
Standard Python NumPy
1 a = range(10000000) 1 import numpy as np
2 b = range(10000000) 2 a = np.arange(10000000)
3 c = [] 3 b = np.arange(10000000)
4 for i in range(len(a)): 4 c = a + b
5 c.append(a[i] + b[i])
5-10 seconds “nearly instantaneous”
29. 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
44. 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
45. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
46. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
47. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
48. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
49. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
50. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
51. String Methods
$ python string_methods.py
1 print ' string value '.split() ['string', 'value']
2 print ' string value '.strip() string value
3 print 'str' in ' string value ' True
4 print 'CHUGALUG'.startswith('C') True
5 print 'CHUGALUG'.endswith('end') False
6 print ':'.join(['a', 'b', 'c']) a:b:c
52. Function and Method Scope
1 class MyClass(object):
2
3 def do_something(self, arg1, arg2):
4 return arg1 * arg2
5
6 def my_function(arg1, arg2):
7 return arg1 * arg2
53. Dynamic Attribute Lookup
1 class MyClass(object):
2
3 CLASS_ATTR = 'class value'
4
5 def __init__(self, arg):
6 self.attr = arg
7
8 o = MyClass('instance value')
9 print o.attr
10 print o.CLASS_ATTR
$ python dynamic_attribute_lookup.py
instance value
class value
54. Dynamic Typing
1 class A(object):
2 def do_something(self):
3 print 'in A'
4
5 class B(object): $ python dynamic_typing.py
6 def do_something(self): in A
7 print 'in B' 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)
55. 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
65. 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 <module>
print f('5')
File ".../traceback.py", line 3, in f
return n * f(n-1)
TypeError: unsupported operand type(s) for -: 'str' and 'int'
66. 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 <module>
print f('5')
File ".../raising.py", line 3, in f
raise TypeError('n should be an int')
TypeError: n should be an int
67. 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 <module>
print f('5')
File ".../raising.py", line 3, in f
raise TypeError('n should be an int')
TypeError: n should be an int
69. 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
70. In the face of ambiguity, refuse the temptation to
guess.
• Coerce types only when not
surprising
• Cannot add strings and
numbers
• Can multiply them!
76. There should be one – and
preferably only one – way to
do it.
• Eliminate redundancy
• Easier to learn
• Easier to remember
77. Index API
1 a = [ 1, 2, 3 ]
2 print a[0]
3
4 a = (1, 2, 3)
5 print a[0] $ python index_api.py
6 1
7 a = 'abc' 1
8 print a[0] a
9 zero value
10 a = {0:'zero value',
11 1:'one value',
12 }
13 print a[0]
78. Although that way may not
be obvious at first unless
you’re Dutch.
• GUI • Django
• GTK • AppEngine
• KDE • Pyramid
• Cocoa • Flask
• MS • TurboGear
Windows s
• Tk • Pecan
• wxPython
• Web
79. Now is better than
never.
• ctypes
• Jython
• IronPython
• Python 2 vs. Python 3
80. Although never is often
better than right now.
• Language moratorium
• Not everything goes into stdlib
any more