SlideShare a Scribd company logo
Python Puzzlers
Feb 17, 2016
Nandan Sawant, Ryan Rueth
1. Defaulter
Defaulter
def extend_list(val, l=[]):
l.append(val)
return l
list1 = extend_list(10)
list2 = extend_list(123,[])
list3 = extend_list('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
Defaulter
def extend_list(val, l=[]):
l.append(val)
return l
list1 = extend_list(10)
list2 = extend_list(123,[])
list3 = extend_list('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']
Defaulter
From the python documentation:
https://docs.python.org/2/reference/compound_stmts.html#function-definitions
● Avoid mutable default arguments
● If you use mutable default arguments,
○ don’t mutate them
○ have a good reason to mutate them (e.g. caching)
Defaulter
def extend_list(val, l=None):
if l is None:
l = []
l.append(val)
return l
list1 = extend_list(10)
list2 = extend_list(123,[])
list3 = extend_list('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
list1 = [10]
list2 = [123]
list3 = ['a']
2. Who’s late?
Who’s late?
multipliers = [lambda x: (i+1)*x for i in range(10)]
def print_multiplication_table_for(number):
print [multiplier(number) for multiplier in multipliers]
print_multiplication_table_for(2)
Who’s late?
multipliers = [lambda x: (i+1)*x for i in range(10)]
def print_multiplication_table_for(number):
print [multiplier(number) for multiplier in multipliers]
print_multiplication_table_for(2)
[20, 20, 20, 20, 20, 20, 20, 20, 20, 20]
Who’s late?
multipliers = []
for i in range(10):
def multiplier(x):
return (i+1) * x
multipliers.append(multiplier)
def print_multiplication_table_for(number):
print [multiplier(number) for multiplier in multipliers]
print_multiplication_table_for(2)
Who’s late?
multipliers = []
for i in range(10):
def multiplier(x):
return (i+1) * x
multipliers.append(multiplier)
def print_multiplication_table_for(number):
print [multiplier(number) for multiplier in multipliers]
print_multiplication_table_for(2)
[20, 20, 20, 20, 20, 20, 20, 20, 20, 20]
● A closure occurs when a function has access to a local variable from
an enclosing scope that has finished its execution
● Closures in python are late-binding
● This means that the values of variables used in closures are looked
up at the time the closure is called
● This behavior is NOT specific to lambdas
Who’s late?
Who’s late?
multipliers = [lambda x, i=i: (i+1)*x for i in range(10)]
def print_multiplication_table_for(number):
print [multiplier(number) for multiplier in multipliers]
print_multiplication_table_for(2)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Who’s late?
from functools import partial
from operator import mul
multipliers = [partial(mul, i+1) for i in range(10)]
def print_multiplication_table_for(number):
print [multiplier(number) for multiplier in multipliers]
print_multiplication_table_for(2)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
3. Western Addition
Western Addition (A)
Western Addition (A)
a = b = [1,2,3]
a += [4]
print a, b
a = a + [5]
print a, b
Western Addition (A)
a = b = [1,2,3]
a += [4]
print a, b
a = a + [5]
print a, b
[1, 2, 3, 4] [1, 2, 3, 4]
[1, 2, 3, 4, 5] [1, 2, 3, 4]
● a + b uses __add__ while a += b uses __iadd__
● An object's __add__ method is regular addition: it takes two
parameters, returns their sum, and doesn't modify either parameter
● An object's __iadd__ method also takes two parameters, but makes
the change in-place, modifying the contents of the first parameter
Western Addition (A)
Western Addition (B)
Western Addition (B)
a = b = 'western'
a += 'addition'
print a, b
a = a + 'sf'
print a, b
Western Addition (B)
a = b = 'western'
a += 'addition'
print a, b
a = a + 'sf'
print a, b
westernaddition western
westernadditionsf western
● a + b uses __add__ while a += b uses __iadd__, if it exists
● An object's __add__ method is regular addition: it takes two
parameters, returns their sum, and doesn't modify either parameter
● An object's __iadd__ method also takes two parameters, but makes
the change in-place, modifying the contents of the first parameter
● Because this requires object mutation, immutable types (like
Strings!) don’t have an __iadd__ method
Western Addition (B)
Western Addition (C)
Western Addition (C)
a = ([1,2,3],)
a[0] += [4]
print a
Western Addition (C)
a = ([1,2,3],)
a[0] += [4]
print a
TypeError: 'tuple' object does
not support item assignment
([1, 2, 3, 4],)
● An object's __iadd__ method takes two parameters, but makes the
change in-place, modifying the contents of the first parameter and
returns the first parameter
● The code above is equivalent to:
Western Addition (C)
a = ([1,2,3],)
x = a[0]
x = x.__iadd__([4]) # returns x itself
a[0] = x
Western Addition (D)
Western Addition (D)
a = b = 500
print a is b
a -= 200
b -= 200
print a is b
a = a - 200
b = b - 200
print a is b
--a
--b
print a is b
Western Addition (D)
a = b = 500
print a is b
a -= 200
b -= 200
print a is b
a = a - 200
b = b - 200
print a is b
--a
--b
print a is b
True
False
True
True
From the python documentation:
https://docs.python.org/2/c-api/int.html
Western Addition (D)
● There is no decrement (--) operator in python
● -- is simply two negation operators
4. Crossing the Boundary
Crossing the Boundary (A)
Crossing the Boundary (A)
a, b = 0, 1
def fib(n):
for i in range(n):
a, b = b, a + b
return a
print fib(4)
Crossing the Boundary (A)
a, b = 0, 1
def fib(n):
for i in range(n):
a, b = b, a + b
return a
print fib(4)
UnboundLocalError: local
variable 'b' referenced before
assignment
Crossing the Boundary (A)
x = 1
def f1():
print x
f1()
print x
x = 1
def f2():
x = 2
print x
f2()
print x
x = 1
def f3():
print x
x = 3
f3()
print x
Crossing the Boundary (A)
x = 1
def f1():
print x
f1()
print x
x = 1
def f2():
x = 2
print x
f2()
print x
x = 1
def f3():
print x
x = 3
f3()
print x
1
1
2
1
UnboundLocalError: local
variable 'x' referenced
before assignment
1
● If we want to access a global variable from inside a function, it is
possible
● The assignment statement inside a function creates variables in the
local scope
● If a local variable has the same name as a global variable the local
variable will always take precedence
● The assignment inside the function does not modify the global
variable
● We may not refer to both a global variable and a local variable by
the same name inside the same function, it gives us an error
● Deep Dive http://eli.thegreenplace.net/2011/05/15/understanding-unboundlocalerror-in-python
Crossing the Boundary (A)
Crossing the Boundary (A)
a, b = 0, 1
def fib(n):
for i in range(n):
global a, b
a, b = b, a + b
return a
print fib(4) 3
Crossing the Boundary (B)
Crossing the Boundary (B)
Crossing the Boundary (B)
Crossing the Boundary (C)
Crossing the Boundary (C)
main.py
try:
import quitter
except:
exit(0)
quitter.quit()
quitter.py
def quit():
exit(0)
# Add one indented line here
# to make main.py crash
python main.py
Crossing the Boundary (C)
main.py
try:
import quitter
except:
exit(0)
quitter.quit()
quitter.py
def quit():
exit(0)
exit = None
python main.py
Crossing the Boundary (C)
main.py
try:
import quitter
except:
exit(0)
quitter.quit()
quitter.py
def quit():
exit(0)
exit = None
UnboundLocalError: local variable
'exit' referenced before assignment
python main.py
5. Kids These Days
Kids These Days (A)
Kids These Days (A)
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x
Kids These Days (A)
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x
1 1 1
1 2 1
3 2 3
● In Python, class variables are internally handled as dictionaries.
● If a variable name is not found in the dictionary of the current class,
the class hierarchy (i.e., its parent classes) are searched until the
referenced variable name is found
● If the referenced variable name is not found in the class itself or
anywhere in its hierarchy, an AttributeError occurs
Kids These Days (A)
Kids These Days (B)
Kids These Days (B)
class Parent:
x = 1
class Child1(Parent):
pass
class Child2(Parent):
x = 2
class GrandChild(Child1, Child2):
pass
print GrandChild.x
Kids These Days (B)
class Parent:
x = 1
class Child1(Parent):
pass
class Child2(Parent):
x = 2
class GrandChild(Child1, Child2):
pass
print GrandChild.x 1
Kids These Days (B)
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
x = 2
class GrandChild(Child1, Child2):
pass
print GrandChild.x 2
● If you don’t inherit from ‘object’, you’re defining an old style class
● MRO is Method Resolution Order. Lookup __mro__
● MRO for old style classes follows a native DFS approach
Grandchild -> Child 1 -> Parent -> Child 2 -> Parent
● MRO for new style classes is more sensible
Grandchild -> Child 1 -> Child 2 -> Parent
● Don’t use old-style classes
Kids These Days (B)
6. Exceptional Circumstances
Exceptional Circumstances
user_id = 'a'
try:
user_id = int(user_id)
print user_id
except TypeError, ValueError:
print "Oops!"
(a) a
(b) 65
(c) Oops!
(d) raises TypeError
(e) raises ValueError
Exceptional Circumstances
user_id = 'a'
try:
user_id = int(user_id)
print user_id
except TypeError, ValueError:
print "Oops!"
(a) a
(b) 65
(c) Oops!
(d) raises TypeError
(e) raises ValueError
ValueError: invalid literal
for int() with base 10: 'a'
Exceptional Circumstances
user_id = 'a'
try:
user_id = int(user_id)
print user_id
except (TypeError, ValueError):
print "Oops!"
(a) a
(b) 65
(c) Oops!
(d) raises TypeError
(e) raises ValueError
● If you’re catching multiple exceptions in python 2.x,
you must enclose them in parentheses
● If you do not, the second argument to except is treated as a
reference to the exception object. E.g. this may look familiar:
except Exception, e
● This problem goes away in python 3.x as
except Exception, e
is not a valid syntax. It is replaced by
except Exception as e
Exceptional Circumstances
7. So long!
So long!
x = set([type(1), type(1L), type(1.0)])
y = set([1.__class__, 1L.__class__, 1.0.__class__])
print x == y
(a) True
(b) False
(c) TypeError
(d) None of the above
So long!
x = set([type(1), type(1L), type(1.0)])
y = set([1.__class__, 1L.__class__, 1.0.__class__])
print x == y
(a) True
(b) False
(c) TypeError
(d) None of the above
y = set([1.__class__, 1L.__class__, 1.0.__class__])
^
SyntaxError: invalid syntax
It is a tokenization issue!
The . is parsed as the beginning of the fractional part of a floating point
number. When it encounters something other than a number, it will
throw an error.
So long!
So long!
x = set([type(1), type(1L), type(1.0)])
y = set([(1).__class__, 1L.__class__, 1.0.__class__])
print x == y
(a) True
(b) False
(c) TypeError
(d) None of the above
8. Zilch
Zilch
z = False
i = []
l = 0,
c = None
h = {}
print any((z, i, l, c, h))
(a) True
(b) False
(c) (False, False, False, False, False)
(d) None of the above
Zilch
z = False
i = []
l = 0,
c = None
h = {}
print any((z, i, l, c, h))
(a) True
(b) False
(c) (False, False, False, False, False)
(d) None of the above
Zilch
z = False
i = []
l = 0,
c = None
h = {}
print any((z, i, l, c, h))
(a) True
(b) False
(c) (False, False, False, False, False)
(d) None of the above
When creating a tuple, in all cases except the empty tuple, the comma
is the important thing.
Parentheses are only required for other syntactic reasons: to distinguish
a tuple from a set of function arguments, operator precedence, or to
allow line breaks.
Zilch
https://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences
9. It’s 2016!
It’s 2016!
print 2,016 * 2,016
(a) 4064256
(b) 4,064,256
(c) 4 256
(d) 2 32 16
(e) None of the above
It’s 2016!
print 2,016 * 2,016
(a) 4064256
(b) 4,064,256
(c) 4 256
(d) 2 32 16
(e) None of the above
2 28 14
The 0 is an outdated prefix that Python 2.x uses
to represent Octal numbers.
In Python 3, you must write: 0o16 instead.
It’s 2016!
10. Finally
Finally
def find_inverse(n):
inverse = 1
try:
inverse = 1 / k
finally:
return inverse
fi = find_inverse
print fi(-1) + fi(0) + fi(1)
(a) 0
(b) 1
(c) 3
(d) raises ZeroDivisionError
(e) raises NameError
(f) None of the above
Finally
def find_inverse(n):
inverse = 1
try:
inverse = 1 / k
finally:
return inverse
fi = find_inverse
print fi(-1) + fi(0) + fi(1)
(a) 0
(b) 1
(c) 3
(d) raises ZeroDivisionError
(e) raises NameError
(f) None of the above
Finally
return in finally will swallow the actual return value in the try block
return in finally will swallow the exception
Finally
References
● How to format code within a presentation
● Python Puzzlers by Tendayi Mawushe at PyCon Ireland 2010
● Python Puzzlers by Alan Pierce at Khan Academy
● Python Epiphanies by Stuart Williams at PyCon Montreal 2015
● Python Interview Questions
● Python Gotchas
● Raymon Hettinger’s twitter feed @raymondh

More Related Content

PDF
Python Puzzlers
PDF
Object Orientation vs Functional Programming in Python
PPTX
Basics of Python programming (part 2)
PDF
Matlab and Python: Basic Operations
PDF
Learn 90% of Python in 90 Minutes
PDF
Advanced Python, Part 1
PPTX
FUNCTIONS IN PYTHON. CBSE +2 COMPUTER SCIENCE
PDF
Advanced Python, Part 2
Python Puzzlers
Object Orientation vs Functional Programming in Python
Basics of Python programming (part 2)
Matlab and Python: Basic Operations
Learn 90% of Python in 90 Minutes
Advanced Python, Part 1
FUNCTIONS IN PYTHON. CBSE +2 COMPUTER SCIENCE
Advanced Python, Part 2

What's hot (20)

PPTX
13. Java text processing
ODP
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
PPTX
Introduction to Python and TensorFlow
PDF
Analysis of Fatal Utah Avalanches with Python. From Scraping, Analysis, to In...
PDF
Functions in python
PPTX
PDF
Logic programming a ruby perspective
PDF
Introduction to python
PDF
Python Tutorial
PPTX
07. Java Array, Set and Maps
PPTX
Learn python in 20 minutes
PPTX
16. Java stacks and queues
ODP
Python quickstart for programmers: Python Kung Fu
PPTX
Python 표준 라이브러리
PPTX
Java 7, 8 & 9 - Moving the language forward
PDF
Python Modules, Packages and Libraries
PDF
FUNCTIONS IN PYTHON, CLASS 12 COMPUTER SCIENCE
PDF
Declarative Thinking, Declarative Practice
PPSX
DISE - Windows Based Application Development in Java
PPTX
Java fundamentals
13. Java text processing
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
Introduction to Python and TensorFlow
Analysis of Fatal Utah Avalanches with Python. From Scraping, Analysis, to In...
Functions in python
Logic programming a ruby perspective
Introduction to python
Python Tutorial
07. Java Array, Set and Maps
Learn python in 20 minutes
16. Java stacks and queues
Python quickstart for programmers: Python Kung Fu
Python 표준 라이브러리
Java 7, 8 & 9 - Moving the language forward
Python Modules, Packages and Libraries
FUNCTIONS IN PYTHON, CLASS 12 COMPUTER SCIENCE
Declarative Thinking, Declarative Practice
DISE - Windows Based Application Development in Java
Java fundamentals
Ad

Viewers also liked (10)

ODP
Inro to Secure Sockets Layer: SSL
PPTX
Intro to Python Programming Language
PDF
Mastering Python 3 I/O (Version 2)
PDF
Object-oriented Programming in Python
PDF
Python Advanced – Building on the foundation
PPT
Python Programming Language
PPT
Introduction to Python
PDF
Python入門 : 4日間コース社内トレーニング
PDF
PyCon Taiwan 2013 Tutorial
PPT
Introduction to Python
Inro to Secure Sockets Layer: SSL
Intro to Python Programming Language
Mastering Python 3 I/O (Version 2)
Object-oriented Programming in Python
Python Advanced – Building on the foundation
Python Programming Language
Introduction to Python
Python入門 : 4日間コース社内トレーニング
PyCon Taiwan 2013 Tutorial
Introduction to Python
Ad

Similar to Python Puzzlers - 2016 Edition (20)

PDF
Python to scala
PDF
Lecture 5: Functional Programming
PDF
Advanced python
PDF
Introduction to Functional Programming
PDF
The Ring programming language version 1.7 book - Part 35 of 196
PDF
Framework for Extensible, Asynchronous Task Scheduling (FEATS) in Fortran
PDF
The Ring programming language version 1.5.1 book - Part 174 of 180
PPTX
1. Week 1_ Functions and Evaluate Functions.pptx
PDF
The Ring programming language version 1.9 book - Part 98 of 210
PDF
Introduction to ad-3.4, an automatic differentiation library in Haskell
PDF
Introduction to ad-3.4, an automatic differentiation library in Haskell
PPTX
Functions and Relations
PDF
The Ring programming language version 1.5.1 book - Part 30 of 180
ODP
Functors, applicatives, monads
PPTX
Chapter 02 functions -class xii
PPT
Functional object
PDF
Intro to Python
PDF
cel shading as PDF and Python description
PDF
Functions, Types, Programs and Effects
PDF
Fp in scala part 2
Python to scala
Lecture 5: Functional Programming
Advanced python
Introduction to Functional Programming
The Ring programming language version 1.7 book - Part 35 of 196
Framework for Extensible, Asynchronous Task Scheduling (FEATS) in Fortran
The Ring programming language version 1.5.1 book - Part 174 of 180
1. Week 1_ Functions and Evaluate Functions.pptx
The Ring programming language version 1.9 book - Part 98 of 210
Introduction to ad-3.4, an automatic differentiation library in Haskell
Introduction to ad-3.4, an automatic differentiation library in Haskell
Functions and Relations
The Ring programming language version 1.5.1 book - Part 30 of 180
Functors, applicatives, monads
Chapter 02 functions -class xii
Functional object
Intro to Python
cel shading as PDF and Python description
Functions, Types, Programs and Effects
Fp in scala part 2

Recently uploaded (20)

PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PDF
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PDF
iTop VPN Free 5.6.0.5262 Crack latest version 2025
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
Download FL Studio Crack Latest version 2025 ?
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Cost to Outsource Software Development in 2025
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PPTX
L1 - Introduction to python Backend.pptx
PDF
Nekopoi APK 2025 free lastest update
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Complete Guide to Website Development in Malaysia for SMEs
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
How to Choose the Right IT Partner for Your Business in Malaysia
Advanced SystemCare Ultimate Crack + Portable (2025)
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Monitoring Stack: Grafana, Loki & Promtail
iTop VPN Free 5.6.0.5262 Crack latest version 2025
Autodesk AutoCAD Crack Free Download 2025
Download FL Studio Crack Latest version 2025 ?
Wondershare Filmora 15 Crack With Activation Key [2025
Cost to Outsource Software Development in 2025
Oracle Fusion HCM Cloud Demo for Beginners
L1 - Introduction to python Backend.pptx
Nekopoi APK 2025 free lastest update
Reimagine Home Health with the Power of Agentic AI​
Complete Guide to Website Development in Malaysia for SMEs
Design an Analysis of Algorithms I-SECS-1021-03
Odoo Companies in India – Driving Business Transformation.pdf
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development

Python Puzzlers - 2016 Edition

  • 1. Python Puzzlers Feb 17, 2016 Nandan Sawant, Ryan Rueth
  • 3. Defaulter def extend_list(val, l=[]): l.append(val) return l list1 = extend_list(10) list2 = extend_list(123,[]) list3 = extend_list('a') print "list1 = %s" % list1 print "list2 = %s" % list2 print "list3 = %s" % list3
  • 4. Defaulter def extend_list(val, l=[]): l.append(val) return l list1 = extend_list(10) list2 = extend_list(123,[]) list3 = extend_list('a') print "list1 = %s" % list1 print "list2 = %s" % list2 print "list3 = %s" % list3 list1 = [10, 'a'] list2 = [123] list3 = [10, 'a']
  • 5. Defaulter From the python documentation: https://docs.python.org/2/reference/compound_stmts.html#function-definitions ● Avoid mutable default arguments ● If you use mutable default arguments, ○ don’t mutate them ○ have a good reason to mutate them (e.g. caching)
  • 6. Defaulter def extend_list(val, l=None): if l is None: l = [] l.append(val) return l list1 = extend_list(10) list2 = extend_list(123,[]) list3 = extend_list('a') print "list1 = %s" % list1 print "list2 = %s" % list2 print "list3 = %s" % list3 list1 = [10] list2 = [123] list3 = ['a']
  • 8. Who’s late? multipliers = [lambda x: (i+1)*x for i in range(10)] def print_multiplication_table_for(number): print [multiplier(number) for multiplier in multipliers] print_multiplication_table_for(2)
  • 9. Who’s late? multipliers = [lambda x: (i+1)*x for i in range(10)] def print_multiplication_table_for(number): print [multiplier(number) for multiplier in multipliers] print_multiplication_table_for(2) [20, 20, 20, 20, 20, 20, 20, 20, 20, 20]
  • 10. Who’s late? multipliers = [] for i in range(10): def multiplier(x): return (i+1) * x multipliers.append(multiplier) def print_multiplication_table_for(number): print [multiplier(number) for multiplier in multipliers] print_multiplication_table_for(2)
  • 11. Who’s late? multipliers = [] for i in range(10): def multiplier(x): return (i+1) * x multipliers.append(multiplier) def print_multiplication_table_for(number): print [multiplier(number) for multiplier in multipliers] print_multiplication_table_for(2) [20, 20, 20, 20, 20, 20, 20, 20, 20, 20]
  • 12. ● A closure occurs when a function has access to a local variable from an enclosing scope that has finished its execution ● Closures in python are late-binding ● This means that the values of variables used in closures are looked up at the time the closure is called ● This behavior is NOT specific to lambdas Who’s late?
  • 13. Who’s late? multipliers = [lambda x, i=i: (i+1)*x for i in range(10)] def print_multiplication_table_for(number): print [multiplier(number) for multiplier in multipliers] print_multiplication_table_for(2) [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
  • 14. Who’s late? from functools import partial from operator import mul multipliers = [partial(mul, i+1) for i in range(10)] def print_multiplication_table_for(number): print [multiplier(number) for multiplier in multipliers] print_multiplication_table_for(2) [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
  • 17. Western Addition (A) a = b = [1,2,3] a += [4] print a, b a = a + [5] print a, b
  • 18. Western Addition (A) a = b = [1,2,3] a += [4] print a, b a = a + [5] print a, b [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4, 5] [1, 2, 3, 4]
  • 19. ● a + b uses __add__ while a += b uses __iadd__ ● An object's __add__ method is regular addition: it takes two parameters, returns their sum, and doesn't modify either parameter ● An object's __iadd__ method also takes two parameters, but makes the change in-place, modifying the contents of the first parameter Western Addition (A)
  • 21. Western Addition (B) a = b = 'western' a += 'addition' print a, b a = a + 'sf' print a, b
  • 22. Western Addition (B) a = b = 'western' a += 'addition' print a, b a = a + 'sf' print a, b westernaddition western westernadditionsf western
  • 23. ● a + b uses __add__ while a += b uses __iadd__, if it exists ● An object's __add__ method is regular addition: it takes two parameters, returns their sum, and doesn't modify either parameter ● An object's __iadd__ method also takes two parameters, but makes the change in-place, modifying the contents of the first parameter ● Because this requires object mutation, immutable types (like Strings!) don’t have an __iadd__ method Western Addition (B)
  • 25. Western Addition (C) a = ([1,2,3],) a[0] += [4] print a
  • 26. Western Addition (C) a = ([1,2,3],) a[0] += [4] print a TypeError: 'tuple' object does not support item assignment ([1, 2, 3, 4],)
  • 27. ● An object's __iadd__ method takes two parameters, but makes the change in-place, modifying the contents of the first parameter and returns the first parameter ● The code above is equivalent to: Western Addition (C) a = ([1,2,3],) x = a[0] x = x.__iadd__([4]) # returns x itself a[0] = x
  • 29. Western Addition (D) a = b = 500 print a is b a -= 200 b -= 200 print a is b a = a - 200 b = b - 200 print a is b --a --b print a is b
  • 30. Western Addition (D) a = b = 500 print a is b a -= 200 b -= 200 print a is b a = a - 200 b = b - 200 print a is b --a --b print a is b True False True True
  • 31. From the python documentation: https://docs.python.org/2/c-api/int.html Western Addition (D) ● There is no decrement (--) operator in python ● -- is simply two negation operators
  • 32. 4. Crossing the Boundary
  • 34. Crossing the Boundary (A) a, b = 0, 1 def fib(n): for i in range(n): a, b = b, a + b return a print fib(4)
  • 35. Crossing the Boundary (A) a, b = 0, 1 def fib(n): for i in range(n): a, b = b, a + b return a print fib(4) UnboundLocalError: local variable 'b' referenced before assignment
  • 36. Crossing the Boundary (A) x = 1 def f1(): print x f1() print x x = 1 def f2(): x = 2 print x f2() print x x = 1 def f3(): print x x = 3 f3() print x
  • 37. Crossing the Boundary (A) x = 1 def f1(): print x f1() print x x = 1 def f2(): x = 2 print x f2() print x x = 1 def f3(): print x x = 3 f3() print x 1 1 2 1 UnboundLocalError: local variable 'x' referenced before assignment 1
  • 38. ● If we want to access a global variable from inside a function, it is possible ● The assignment statement inside a function creates variables in the local scope ● If a local variable has the same name as a global variable the local variable will always take precedence ● The assignment inside the function does not modify the global variable ● We may not refer to both a global variable and a local variable by the same name inside the same function, it gives us an error ● Deep Dive http://eli.thegreenplace.net/2011/05/15/understanding-unboundlocalerror-in-python Crossing the Boundary (A)
  • 39. Crossing the Boundary (A) a, b = 0, 1 def fib(n): for i in range(n): global a, b a, b = b, a + b return a print fib(4) 3
  • 44. Crossing the Boundary (C) main.py try: import quitter except: exit(0) quitter.quit() quitter.py def quit(): exit(0) # Add one indented line here # to make main.py crash python main.py
  • 45. Crossing the Boundary (C) main.py try: import quitter except: exit(0) quitter.quit() quitter.py def quit(): exit(0) exit = None python main.py
  • 46. Crossing the Boundary (C) main.py try: import quitter except: exit(0) quitter.quit() quitter.py def quit(): exit(0) exit = None UnboundLocalError: local variable 'exit' referenced before assignment python main.py
  • 49. Kids These Days (A) class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print Parent.x, Child1.x, Child2.x Child1.x = 2 print Parent.x, Child1.x, Child2.x Parent.x = 3 print Parent.x, Child1.x, Child2.x
  • 50. Kids These Days (A) class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print Parent.x, Child1.x, Child2.x Child1.x = 2 print Parent.x, Child1.x, Child2.x Parent.x = 3 print Parent.x, Child1.x, Child2.x 1 1 1 1 2 1 3 2 3
  • 51. ● In Python, class variables are internally handled as dictionaries. ● If a variable name is not found in the dictionary of the current class, the class hierarchy (i.e., its parent classes) are searched until the referenced variable name is found ● If the referenced variable name is not found in the class itself or anywhere in its hierarchy, an AttributeError occurs Kids These Days (A)
  • 53. Kids These Days (B) class Parent: x = 1 class Child1(Parent): pass class Child2(Parent): x = 2 class GrandChild(Child1, Child2): pass print GrandChild.x
  • 54. Kids These Days (B) class Parent: x = 1 class Child1(Parent): pass class Child2(Parent): x = 2 class GrandChild(Child1, Child2): pass print GrandChild.x 1
  • 55. Kids These Days (B) class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): x = 2 class GrandChild(Child1, Child2): pass print GrandChild.x 2
  • 56. ● If you don’t inherit from ‘object’, you’re defining an old style class ● MRO is Method Resolution Order. Lookup __mro__ ● MRO for old style classes follows a native DFS approach Grandchild -> Child 1 -> Parent -> Child 2 -> Parent ● MRO for new style classes is more sensible Grandchild -> Child 1 -> Child 2 -> Parent ● Don’t use old-style classes Kids These Days (B)
  • 58. Exceptional Circumstances user_id = 'a' try: user_id = int(user_id) print user_id except TypeError, ValueError: print "Oops!" (a) a (b) 65 (c) Oops! (d) raises TypeError (e) raises ValueError
  • 59. Exceptional Circumstances user_id = 'a' try: user_id = int(user_id) print user_id except TypeError, ValueError: print "Oops!" (a) a (b) 65 (c) Oops! (d) raises TypeError (e) raises ValueError ValueError: invalid literal for int() with base 10: 'a'
  • 60. Exceptional Circumstances user_id = 'a' try: user_id = int(user_id) print user_id except (TypeError, ValueError): print "Oops!" (a) a (b) 65 (c) Oops! (d) raises TypeError (e) raises ValueError
  • 61. ● If you’re catching multiple exceptions in python 2.x, you must enclose them in parentheses ● If you do not, the second argument to except is treated as a reference to the exception object. E.g. this may look familiar: except Exception, e ● This problem goes away in python 3.x as except Exception, e is not a valid syntax. It is replaced by except Exception as e Exceptional Circumstances
  • 63. So long! x = set([type(1), type(1L), type(1.0)]) y = set([1.__class__, 1L.__class__, 1.0.__class__]) print x == y (a) True (b) False (c) TypeError (d) None of the above
  • 64. So long! x = set([type(1), type(1L), type(1.0)]) y = set([1.__class__, 1L.__class__, 1.0.__class__]) print x == y (a) True (b) False (c) TypeError (d) None of the above y = set([1.__class__, 1L.__class__, 1.0.__class__]) ^ SyntaxError: invalid syntax
  • 65. It is a tokenization issue! The . is parsed as the beginning of the fractional part of a floating point number. When it encounters something other than a number, it will throw an error. So long!
  • 66. So long! x = set([type(1), type(1L), type(1.0)]) y = set([(1).__class__, 1L.__class__, 1.0.__class__]) print x == y (a) True (b) False (c) TypeError (d) None of the above
  • 68. Zilch z = False i = [] l = 0, c = None h = {} print any((z, i, l, c, h)) (a) True (b) False (c) (False, False, False, False, False) (d) None of the above
  • 69. Zilch z = False i = [] l = 0, c = None h = {} print any((z, i, l, c, h)) (a) True (b) False (c) (False, False, False, False, False) (d) None of the above
  • 70. Zilch z = False i = [] l = 0, c = None h = {} print any((z, i, l, c, h)) (a) True (b) False (c) (False, False, False, False, False) (d) None of the above
  • 71. When creating a tuple, in all cases except the empty tuple, the comma is the important thing. Parentheses are only required for other syntactic reasons: to distinguish a tuple from a set of function arguments, operator precedence, or to allow line breaks. Zilch https://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences
  • 73. It’s 2016! print 2,016 * 2,016 (a) 4064256 (b) 4,064,256 (c) 4 256 (d) 2 32 16 (e) None of the above
  • 74. It’s 2016! print 2,016 * 2,016 (a) 4064256 (b) 4,064,256 (c) 4 256 (d) 2 32 16 (e) None of the above 2 28 14
  • 75. The 0 is an outdated prefix that Python 2.x uses to represent Octal numbers. In Python 3, you must write: 0o16 instead. It’s 2016!
  • 77. Finally def find_inverse(n): inverse = 1 try: inverse = 1 / k finally: return inverse fi = find_inverse print fi(-1) + fi(0) + fi(1) (a) 0 (b) 1 (c) 3 (d) raises ZeroDivisionError (e) raises NameError (f) None of the above
  • 78. Finally def find_inverse(n): inverse = 1 try: inverse = 1 / k finally: return inverse fi = find_inverse print fi(-1) + fi(0) + fi(1) (a) 0 (b) 1 (c) 3 (d) raises ZeroDivisionError (e) raises NameError (f) None of the above
  • 80. return in finally will swallow the actual return value in the try block return in finally will swallow the exception Finally
  • 81. References ● How to format code within a presentation ● Python Puzzlers by Tendayi Mawushe at PyCon Ireland 2010 ● Python Puzzlers by Alan Pierce at Khan Academy ● Python Epiphanies by Stuart Williams at PyCon Montreal 2015 ● Python Interview Questions ● Python Gotchas ● Raymon Hettinger’s twitter feed @raymondh