You are on page 1of 88

# An Introduction to

## the Zen of Python

Doug Hellmann
February, 2011
Friday, February 18, 2011
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 Dutch.
• Flat is better than nested. • Now is better than never.
• Sparse is better than dense. • Although never is often better than
• Special cases aren't special enough • If the implementation is hard to
to break the rules. explain, it's a bad idea.
• Although practicality beats purity. • If the implementation is easy to
• Errors should never pass silently. explain, it may be a good idea.
• Unless explicitly silenced. • Namespaces are one honking great
• In the face of ambiguity, refuse the idea – let's do more of those!
temptation to guess.

## Friday, February 18, 2011

Beautiful is better
than ugly.

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

Explicit is better than
implicit.

• Boolean type

inside a method

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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()

## Friday, February 18, 2011

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()

## Friday, February 18, 2011

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()

## Friday, February 18, 2011

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()

## Friday, February 18, 2011

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()

## Friday, February 18, 2011

Simple is better than
complex.

• Garbage collection

• print statement

experimentation

## Friday, February 18, 2011

Printing
1 # -*- encoding: utf-8 -*-
2
3 print 'string:', 'string'
4
5 print 'unicode:', u'üñîçø∂é string'
6
7 print 'number:', 5 * 5
8
9 my_list = [ 1, 'a', None ]
10 print 'list:', my_list
11
12 my_dict = { 'a':'a value', 'b':'b value' }
13 print 'dict:', my_dict

\$ python printing.py
string: string
unicode: üñîçø∂é string
number: 25
list: [1, 'a', None]
dict: {'a': 'a value', 'b': 'b value'}
Friday, February 18, 2011
Printing, with printf-style Formatting
1 # -*- encoding: utf-8 -*-
2
3 my_list = [ 1, 'a', None ]
4 my_dict = { 'a':'a value', 'b':'b value' }
5
6 args = ('string', u'üñîçø∂é string', 5 * 5,
7 my_list, my_dict)
8
9 print '''
10 string : %s
11 unicode: %s
12 number : %d \$ python printing_with_format.py
13 list : %s
14 dict : %s string : string
15 ''' % args unicode: üñîçø∂é string
number : 25
list : [1, 'a', None]
dict : {'a': 'a value', 'b': 'b value'}

## Friday, February 18, 2011

Interactive Interpreter

## Friday, February 18, 2011

Complex is better
than complicated.

• Do complex things in a
“Pythonic” way

science and math

## Friday, February 18, 2011

Interactive Graphic
SciPy, NumPy, matplotlib
Environment
Friday, February 18, 2011
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])

## 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

Standard Library Modules: Networking

• socket • asyncore

• select • asynchat

• SocketServer • xmlrpclib

• BaseHTTPServer • SimpleXMLRPCServer

## Friday, February 18, 2011

Standard Library Modules: Internet Protocols

• urllib • smtplib

• httplib • poplib

• ftplib • imaplib

• smtpd • json

## Friday, February 18, 2011

Standard Library Modules: Command Line

• getopt • fileinput

• optparse • cmd

## Friday, February 18, 2011

Standard Library Modules: Parallel Processing

• subprocess • multiprocessing

## Friday, February 18, 2011

Standard Library Modules: Databases

• anydbm • shelve

• pickle • sqlite3

## Friday, February 18, 2011

Standard Library Modules: Miscellaneous

• datetime • struct

• grp • ctypes

• pwd • xml

• profile • tarfile

• timeit • csv

## Friday, February 18, 2011

Sparse is better than
dense.

## • Standard library stays “shallow”

• http://pypi.python.org/

schedules

packages”)

## • Whitespace for block structures

• Minimal punctuation

• Built-in documentation

## • Extensive online documentation

at http://docs.python.org/

## Friday, February 18, 2011

Code Blocks

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()

## Friday, February 18, 2011

Code Blocks

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()

## Friday, February 18, 2011

Minimal Punctuation

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()

## Friday, February 18, 2011

Minimal Punctuation

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()

## Friday, February 18, 2011

Inline Documentation

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()

## Friday, February 18, 2011

Inline Documentation

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()

## Friday, February 18, 2011

Special cases aren’t special
enough to break the rules.

• Everything is an object

scope

attribute lookup

modules

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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

## Friday, February 18, 2011

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)

## 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

Although practicality
beats purity.

• OOP

• Procedural

• Functional

Procedural

## 1 def my_function(arg1, arg2):

2 """This function multiplies arg1 by arg2.
3 """
4 return arg1 * arg2
5
6 results = []
7 for i in range(5):
8 results.append(my_function(i, i))
9
10 print results

\$ python procedural.py
[0, 1, 4, 9, 16]

## Friday, February 18, 2011

Functional: List Comprehension

## 1 results = [ i*i for i in range(5) ]

2
3 print results

\$ python functional.py
[0, 1, 4, 9, 16]

## Friday, February 18, 2011

Functional: List Comprehension

## 1 results = [ i*i for i in range(5) ]

2
3 print results

\$ python functional.py
[0, 1, 4, 9, 16]

## Friday, February 18, 2011

Functional: List Comprehension

## 1 results = [ i*i for i in range(5) ]

2
3 print results

\$ python functional.py
[0, 1, 4, 9, 16]

## Friday, February 18, 2011

Functional: List Comprehension

## 1 results = [ i*i for i in range(5) ]

2
3 print results

\$ python functional.py
[0, 1, 4, 9, 16]

## Friday, February 18, 2011

Functional: Generator Expression

## 1 results = ( i*i for i in range(5) )

2
3 print results
4
5 for i in results:
6 print i

1 \$ python generator_expr.py
2 <generator object <genexpr> at 0x1004d20a0>
3 0
4 1
5 4
6 9
7 16

## Friday, February 18, 2011

Functional: Generators

1 def gen_values(n):
2 for i in range(n):
3 yield i*i
4
5 print gen_values(5)
6
7 for i in gen_values(5):
8 print i

1 \$ python generator.py
2 <generator object gen_values at 0x1004d2050>
3 0
4 1
5 4
6 9
7 16

## Friday, February 18, 2011

Errors should never
pass silently.

## 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 <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'

## 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 <module>
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 <module>
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

Unless explicitly
silenced.

try:except

• Process

• Convert

• Ignore

## 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.

surprising

numbers

## Friday, February 18, 2011

Type Coercion

1 print 5 * 1.0
2 print 2 ** 100
3 print 2 * 'abc'
4 print 2 + 'abc'

1 \$ python type_coercion.py
2 5.0
3 1267650600228229401496703205376
4 abcabc
5 Traceback (most recent call last):
6 File ".../type_coercion.py", line 4, in <module>
7 print 2 + 'abc'
8 TypeError: unsupported operand type(s) for +: 'int' and 'str'

## Friday, February 18, 2011

Type Coercion

1 print 5 * 1.0
2 print 2 ** 100
3 print 2 * 'abc'
4 print 2 + 'abc'

1 \$ python type_coercion.py
2 5.0
3 1267650600228229401496703205376
4 abcabc
5 Traceback (most recent call last):
6 File ".../type_coercion.py", line 4, in <module>
7 print 2 + 'abc'
8 TypeError: unsupported operand type(s) for +: 'int' and 'str'

## Friday, February 18, 2011

Type Coercion

1 print 5 * 1.0
2 print 2 ** 100
3 print 2 * 'abc'
4 print 2 + 'abc'

1 \$ python type_coercion.py
2 5.0
3 1267650600228229401496703205376
4 abcabc
5 Traceback (most recent call last):
6 File ".../type_coercion.py", line 4, in <module>
7 print 2 + 'abc'
8 TypeError: unsupported operand type(s) for +: 'int' and 'str'

## Friday, February 18, 2011

Type Coercion

1 print 5 * 1.0
2 print 2 ** 100
3 print 2 * 'abc'
4 print 2 + 'abc'

1 \$ python type_coercion.py
2 5.0
3 1267650600228229401496703205376
4 abcabc
5 Traceback (most recent call last):
6 File ".../type_coercion.py", line 4, in <module>
7 print 2 + 'abc'
8 TypeError: unsupported operand type(s) for +: 'int' and 'str'

## Friday, February 18, 2011

Type Coercion

1 print 5 * 1.0
2 print 2 ** 100
3 print 2 * 'abc'
4 print 2 + 'abc'

1 \$ python type_coercion.py
2 5.0
3 1267650600228229401496703205376
4 abcabc
5 Traceback (most recent call last):
6 File ".../type_coercion.py", line 4, in <module>
7 print 2 + 'abc'
8 TypeError: unsupported operand type(s) for +: 'int' and 'str'

## Friday, February 18, 2011

There should be one – and
preferably only one – way to do
it.

• Eliminate redundancy

• Easier to learn

• Easier to remember

## Friday, February 18, 2011

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]

## Friday, February 18, 2011

Although that way may not be
obvious at first unless you’re
Dutch.

• GUI • Web

• GTK • Django

• KDE • AppEngine

• Cocoa • Pyramid

Windows
• TurboGears
• Tk
• Pecan
• wxPython

## Friday, February 18, 2011

Now is better than
never.

• ctypes

• Jython

• IronPython

## Friday, February 18, 2011

Although never is often
better than right now.

• Language moratorium

any more

## Friday, February 18, 2011

If the implementation is hard
Python Enhancement Proposals
to explain, it’s a bad idea.
Friday, February 18, 2011
If the implementation is easy to explain, it may be a
good idea.

## Friday, February 18, 2011

Namespaces are one
honking great idea –
let’s do more of
those!
Closures

## Friday, February 18, 2011

Closures

1 def outer(arg):
2 print 'outer(%s)' % arg
3
4 def inner(val):
5 print 'inner(%s) (arg=%s)' % (val, arg)
6 return val * arg
7
8 return inner
9
10 print 'Creating thrice:'
11 thrice = outer(3)
12
13 print '\nCalling thrice:'
14 print thrice(3)
15 print thrice('a')

## Friday, February 18, 2011

Closures

1 def outer(arg):
2 print 'outer(%s)' % arg
3
4 def inner(val):
5 print 'inner(%s) (arg=%s)' % (val, arg)
6 return val * arg
7
8 return inner \$ python closure.py
9 Creating thrice:
10 print 'Creating thrice:' outer(3)
11 thrice = outer(3)
12 Calling thrice:
13 print '\nCalling thrice:' inner(3) (arg=3)
14 print thrice(3) 9
15 print thrice('a') inner(a) (arg=3)
aaa

## Friday, February 18, 2011

References

• http://docs.python.org/

• http://www.doughellmann.com/
PyMOTW/

David Beazley

## • The Python Standard Library by

Example by Doug Hellmann

• http://us.pycon.org/

Questions?

## Friday, February 18, 2011

Image Credits
1. http://www.gaialandscapedesignbackgrounds.net/landscape_design_architecture_background_Zen_Garden_chan3.htm

13. http://www.flickr.com/photos/tobascodagama/3106398602/

17. http://www.flickr.com/photos/benandliz/11065336/

## 21 & 22. http://scipy.org

24. http://www.otherlandtoys.co.uk/russian-matryoshka-nesting-dolls-pieces-p-2126.html

32. http://www.dandelionsummers.com/html/building_block.html

36. http://www.flickr.com/photos/photoinference/2494576240/in/faves-40068198@N04/

47. http://www.flickr.com/photos/smithsonian/3112472619/in/faves-40068198@N04/

54. http://www.flickr.com/photos/mherring/3722272868/sizes/l/in/photostream/

57. http://www.webstaurantstore.com/9-3-4-x-4-1-2-unbleached-natural-coffee-filter-12-cup-1000-cs/121CF12U.html

59. http://brainstorm-services.com/wcu-lit/ambiguity.html

66. http://commons.wikimedia.org/wiki/File:Dutch_windmill.jpg
67. http://www.epicpm.org/epic-blogging

68. http://www.skyscanner.net/news/articles/2009/09/002990-travel-tip-10-get-on-last-and-learn-the-art-of-patience.html

69. http://gizmodo.com/5015735/the-top-10-rube-goldberg-machines-featured-on-film

71. http://www.nutricaplabs.com/capsule-manufacturer.aspx

75. http://wmltech.wordpress.com/2006/12/09/got-questions/