The document discusses various Python concepts including:
1. The Zen of Python principles for writing beautiful, readable code.
2. Types and objects, including how variables are assigned by reference vs value.
3. Reflection capabilities like accessing an object's attributes, methods, and bytecode.
4. Context managers and how the 'with' statement provides a cleaner interface than try/finally blocks.
5. Decorators for modifying functions and methods.
6. List comprehensions and generators for compactly iterating over sequences.
7. Operator overloading for custom number and container types.
8. Class factories including properties, static methods, and inheritance hierarchies.
3. The Zen of Python
○ 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!
5. Types and objects: To be or not to be
a = 256
b = 256
print (a is b)
a = 257
b = 257
print (a is b)
6. Types and objects: To be or not to be
a = 256
b = 256
print (a is b)
a = 257
b = 257
print (a is b)
True
False
7. Types and objects: To be or not to be
a = 256 a = 256
b = 256 b = 256
print (a is b) print id(a), id(b)
a = 257 a = 257
b = 257 b = 257
print (a is b) print id(a), id(b)
True 22036112 22036112
False 22363568 22363640
8. Types and objects: To be or not to be
a = 256 a = 256
b = 256 b = 256
print (a is b) print id(a), id(b)
a = 257 a = 257
b = 257 b = 257
print (a is b) print id(a), id(b)
True
False
9. Types and objects: To be or not to be
a = 256 a = 256
b = 256 b = 256
print (a is b) print id(a), id(b)
a = 257 a = 257
b = 257 b = 257
print (a is b) print id(a), id(b)
True 22036112 22036112
False 22363568 22363640
10. Types and objects: functions are objects
def x(f):
return f
def y(f):
return x
print x(y)(8)(0)
11. Types and objects: functions are objects
def x(f):
return f
def y(f):
return x
print x(y)(8)(0)
0
12. Types and objects: functions are objects
def x(i):
if x.enabled:
return i
else:
return "disabled"
x.enabled = True
print x(8)
13. Types and objects: functions are objects
def x(i):
if x.enabled:
8
return i
else:
return "disabled"
x.enabled = True
print x(8)
What happened if not set x.enabled?
17. Reflection: get & set
class Example(object):
num = 10
x = Example
dir(x)
hasattr(x, "num") == True
getattr(x, "num", 0) == 10
setattr(x, "num", 20)
18. Reflection: local & global
globals()
Return a dictionary representing the current global symbol table. This is always the dictionary of the
current module (inside a function or method, this is the module where it is defined, not the module from
which it is called).
locals()
Update and return a dictionary representing the current local symbol table. Free
variables are returned by locals() when it is called in function blocks, but not in
class blocks.
19. Reflection: __magic__
__name__
This is the name of the function. This only have a meaningful value is the function is defined with “def”.
__class__
This is a reference to the class a method belongs to.
__code__
This is a reference to the code object used in the implementation of python.
28. Context manager: in the beginning...
item = Item()
try:
item.open()
item.do()
finally:
item.close()
29. Context manager: nowadays...
with Item() as item:
item.do
class Item(object):
def __enter__(self):
self.open()
return self
def __exit__(self,exc_type,exc_value,exc_t):
self.close()
...
30. Context manager: the real world
with file("/tmp/test", "w") as f:
f.write("hello world")
with lock():
# do some concurrent
with sudo("root"):
# do some as root
37. Iterations: comprehesions
squares = []
for x in range(10):
squares.append(x**2)
squares = [x**2 for x in range(10)]
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
{ (k,v) for k,v in [(1,2)] }
38. Iterations: comprehesions
squares = []
for x in range(10):
squares.append(x**2)
squares = [x**2 for x in range(10)]
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
{ (k,v) for k,v in [(1,2)] }
SET NOT DICT!
39. Iterations: comprehesions
squares = []
for x in range(10):
squares.append(x**2)
squares = [x**2 for x in range(10)]
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
{ (k,v) for k,v in [(1,2)] }
SET NOT DICT!
{ k:v for k,v in [(1,2)] }
41. Iterations: co-routine
def countdown(n):
print "Counting down from", n
while n > 0:
yield n
n -= 1
print "Done counting down"
for i in countdown(10):
print i
Counting down from 10
10
9
8
7
6
5
4
3
2
1
Done counting down
42. Iterations: co-routine
def countdown(n):
print "Counting down from", n
while n > 0:
yield n
n -= 1
print "Done counting down"
print countdown(10)
<generator object at 0x4035874c>
50. Overloading: comparison operations
__eq__(self, other) x == y
__lt__(self, other) x<y
__le__(self, other) x <= y
__gt__(self, other) x>y
__ge__(self, other) x >= y
__ne__(self, other) x != y
51. Overloading: containers
__contains__(self, other) y in x
__getitem__(self, other) x[y]
__setitem__(self, other,value) x[y] = z
__delitem__(self, other) del x[y]
__len__(self) len(x)
__reversed__(self) reversed(x)
__iter__(self) iter(x)
53. The Class Factory: class & objects
class Example(object):
attribute = "this is a class attribute"
def __init__(self):
self.attribute = "this is an obj attr override class one"
self.another = "this is another obj attr, no class"
print Example.attribute
print Example().attribute
print Example().another
print Example.another
54. The Class Factory: class & objects
class Example(object):
attribute = "this is a class attribute"
def __init__(self):
self.attribute = "this is an obj attr override class one"
self.another = "this is another obj attr, no class"
print Example.attribute
print Example().attribute
this is a class attribute
print Example().another this is an object attribute and override class one
this is another object attribute, no class
print Example.another
Traceback (most recent call last):
Line 11, in <module>
print Example.another
AttributeError: type object 'Example' has no attribute 'another'
55. The Class Factory: set & get
class Example(object):
def __init__(self):
self._name = x
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
56. The Class Factory: @property abuse
class Example(object):
def __init__(self, host, port):
self.host = host
self.port = port
@property
def connect(self):
lib.connect(self.host, self.port)
57. The Class Factory: @property abuse
class Example(object):
def __init__(self, host, port):
self.host = host
self.port = port
@property
def connect(self):
lib.connect(self.host, self.port)
NEVER TYPE METHODS AS
PROPERTIES
58. The Class Factory: methods and more methods
@staticmethod
Nothing more than a function defined inside a class.
It is callable without instantiating the class first. It’s
definition is immutable via inheritance.
@classmethod
Also callable without instantiating the class, but its
definition follows Sub class, not Parent class, via
inheritance. That’s because the first argument for
@classmethod function must always be cls (class).
59. The Class Factory: methods and more methods
@staticmethod
Nothing more than a function defined inside a class.
It is callable without instantiating the class first. It’s
definition is immutable via inheritance.
@staticmethod
def static_method():
print "I do not receive nothing :("
@classmethod
Also callable without instantiating the class, but its
definition follows Sub class, not Parent class, via
inheritance. That’s because the first argument for
@classmethod function must always be cls (class).
@classmethod
def class_method(cls):
print "I'm a class %s" % str(cls)
60. The Class Factory: methods and more methods
class Example(object):
def __init__(self, name):
self.name = name
@classmethod
def class_method(cls, name):
return cls(name)
x = Example.class_method("example")
print x
61. The Class Factory: methods and more methods
class Example(object):
def __init__(self, name):
self.name = name
@classmethod
def class_method(cls, name):
return cls(name)
x = Example.class_method("example")
print x
<__main__.Example object at 0x40358b2c>
62. The Class Factory: children and parents
class Example(object):
def __init__(self, name):
self.name = name
def do_something(self):
raise NotImplementedError()
class ChildExample(Example):
def do_something(self):
print self.name
63. The Class Factory: children and parents
class ExampleA(object):
def __init__(self, name):
self.name = name
def do_something(self):
raise NotImplementedError()
class ExampleB(object):
def do_otherthing(self):
raise NotImplementedError()
class ChildExample(ExampleB, ExampleA):
def do_something(self):
print self.name
def do_otherthing(self):
print self.name
64. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
x = Example()
y = Example
print x
print y
65. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
x = Example()
y = Example
print x
print y
<__main__.Example object at 0x4035894c>
<class '__main__.Example'>
66. The Class Factory: τὰ μετὰ τὰ κλάση
def example():
class Example(object):
pass
return Example
x = example()
y = x()
print x
print y
67. The Class Factory: τὰ μετὰ τὰ κλάση
def example():
class Example(object):
pass
return Example
x = example()
y = x()
print x
print y
<class '__main__.Example'>
<__main__.Example object at 0x403589ec>
68. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
print type(Example)
print type(Example())
69. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
print type(Example)
print type(Example())
<type 'type'>
<class '__main__.Example'>
70. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
print type(Example)
print type(Example())
<type 'type'>
<class '__main__.Example'>
71. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
print type(Example)
print type(Example())
<type 'type'>
<class '__main__.Example'>
72. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
x = Example
y = type('Example', (object,), {})
print x
print y
print (x == y)
73. The Class Factory: τὰ μετὰ τὰ κλάση
class Example(object):
pass
x = Example
y = type('Example', (object,), {})
print x
print y
print (x == y)
<class '__main__.Example'>
<class '__main__.Example'>
False
74. The Class Factory: __magic__
__new__(cls, *args, **kwargs)
Is the first method to get called in an object's instantiation, is a
@classmethod, and must return a new instance of type cls.
__init__(self, *args, **kwargs)
Is the initializer for the instance. It gets passed whatever the
primary constructor was called with.
__del__(self)
Is the destructor of the instance, will be invoked before clean
the reference to the instance.
75. The Class Factory: __metaclass__
def upper_attr(f_class_name, f_class_parents, f_class_attr):
attrs = ((name, value)
for name, value in f_class_attr.items()
if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value)
for name, value in attrs)
return type(f_class_name, f_class_parents, uppercase_attr)
class Foo(object):
__metaclass__ = upper_attr
bar = 'bip'
print hasattr(Foo, 'bar')
print hasattr(Foo, 'BAR')
76. The Class Factory: __metaclass__
def upper_attr(f_class_name, f_class_parents, f_class_attr):
attrs = ((name, value)
for name, value in f_class_attr.items()
if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value)
for name, value in attrs)
return type(f_class_name, f_class_parents, uppercase_attr)
class Foo(object):
__metaclass__ = upper_attr
bar = 'bip'
print hasattr(Foo, 'bar') False
print hasattr(Foo, 'BAR') True
87. Documentation: Zen
Don't create documentation for your code.
Code your documentation.
def elements(n):
"""Return a list of n numbers from 0 to n-
1.
"""
return range(0,n)
88. Documentation: everything is an object
def elements(n):
"""Return a list of n numbers from 0 to n-
1.
"""
return range(0,n)
print elements.__doc__
89. Documentation: everything is an object
def elements(n):
"""Return a list of n numbers from 0 to n-
1.
"""
return range(0,n)
print elements.__doc__
Return a list of n numbers from 0 to n-1
90. Documentation: style is important
def elements(n):
"""Return a list of n numbers from 0 to n-1.
:type n: int
:param n: the limit upper for the elements to be created (not
included).
:return: a class:`list` with the items.
"""
return range(0,n)
class Example(object):
"""This is the documentation of the class.
Usually you do not need it :)
"""
def __init__(self, param):
"""This is the documentation of the instance type.
"""