a = 'abc'
s = '4 + len(a)'
eval(s)
# string → tokens → AST → bytecode → run
→ 7
# “I need to get an attribute whose
# name I don’t know until runtime—”
eval('my_object.' + attribute_name)
eval('my_object.' + attribute_name)
↓
getattr(my_object, attribute_name)
from collections import namedtuple
Point = namedtuple('Point', 'x y z')
p = Point(3.0, 4.0, 5.0)
print(p.z)
→ 5.0
# How is the new class constructed?
# It uses exec!
_class_template = 'class {typename}...'
⋮
exec _class_template.format(...)
┌────────────┐
│ README.txt │
├────────────┴───────────────────┐
│Adding a float and int together │
│produces a float as output. │
│ │
│>>> 15.0 + 1 │
│16.0 │
│ │
│This is also true for multiply.”│
└────────────────────────────────┘
def count_letters(s):
"""Return a dictionary of letter counts.
>>> count_letters('abba')
{'a': 2, 'b': 2}
"""
counts = {}
for letter in s:
n = counts.get(letter, 0)
counts[letter] = n + 1
return counts
for line in lines:
if line.startswith('>>> '):
expr = line[4:]
expected = next(lines)
result = repr(eval(expr, scope))
if expected != result:
raise Exception()
Syntax “Dunder” Methods
a + b a.__add__(b)
a - b a.__sub__(b)
a < b a.__lt__(b)
repr(a) a.__repr__()
a.b a.__getattribute__('b')
a(b) a.__call__(b)
if a: ...
elif a: ...
while a: ...
'yes' if a else 'no'
[a for a in sequence if a]
(a for a in sequence if a)
if False: if True:
if 0: if 1:
if 0.0: if 1.0:
if '': if 'nonempty string':
if []: if ['non', 'empty', 'list']:
if {}: if {'nonempty': 'dict'}:
if None: if {'non', 'empty', 'set'}:
┌┐
││ ┌┐
┌┐││┌┐ ││┌┐
│└┘│││ │└┘│
└─┐└┘│ │┌─┘ \|/
│┌─┘ ││ |
──────┴┴─────┴┴───────────
def unfriend(subject, users):
if not users:
return
remove_edges('friend', subject, users)
# Q: What’s the type of “users”?
class C:
def __getattr__(self, name):
print('Asked for attribute:', name)
return 5
c = C()
print('c.foo equals', c.foo)
→ Asked for attribute: foo
→ c.foo equals 5
# Proxy Pattern
class Proxy:
def __init__(self, target):
self.target = target
def __getattr__(self, name):
return getattr(self.target, name)
# A "mock" test object
class Mock:
def __init__(self):
self.calls = []
def __getattr__(self, name):
def fake_method(*args):
self.calls.append((name, args))
return fake_method
m = Mock()
m.open('file.txt')
m.close()
assert m.calls == [
('open', ('file.txt',)), ('close', ())
]
from unittest.mock import Mock
def test_layout():
window = Mock()
layout_list(['a', 'b'], window)
assert window.called == [
('text', 0, 0, 'a'),
('text', 0, 12, 'b'),
]
class Template:
def __init__(self, path):
with open(path) as f:
self.text = f.read()
def render(self, **kw):
return self.text.format(**kw)
t = Template('index.html')
t.render(city='Wrocłow', conf='code::dive')
class Template:
def __init__(self, path):
with open(path) as f:
self.text = f.read()
def render(self, **kw):
return self.text.format(**kw)
t = Template('index.html')
t.render(city='Wrocłow', conf='code::dive')
class Template:
def __init__(self, path):
with open(path) as f:
self.text = f.read()
def __call__(self, **kw):
return self.text.format(**kw)
t = Template('index.html')
t(city='Wrocłow', conf='code::dive')
return get_template(args)()()
# build tree of XML element objects
↓
return get_template(args)()()
↑
# flatten to plain text
class Template:
def __call__(...):
...
t = Template()
framework(t) # Needs a callable
class Template:
def render(...):
...
t = Template()
framework(t.render) # Needs a callable
# "t.render" is a "bound method"
import string
string.ascii_letters = ('aąbcćdeęfghijklł'
'mnńoóprsśtuwyzźż')
class C:
value = 1
C.value = 2
print(v.value) # prints “2”
class C:
def method(self):
print('A')
C.method = lambda self: print('B')
obj = C()
obj.method() # prints “B”
# your_web_app.py
def index_view(request):
...
def settings_view(request):
...
def shop_view(request):
...
# your_web_app.py
from framework import request
def index_view():
...
def settings_view():
...
def shop_view():
...
# The framework loads your module.
name = 'your_web_app'
module = __import__(name)
# Then mutates `request` with HTTP data.
request.method = 'GET'
request.url = '/shop/'
response = getattr(module, 'shop_view')()
# The framework loads your module.
name = 'your_web_app'
module = __import__(name)
# Then injects a global named `request`!
module.request = request_object
from unittest.mock import patch
with patch('C.method', replacement_method):
# ...
# indented block runs with altered method
# ...
get_books() fetch() download()
────────────────────────────────────────────────
for isbn in books:
fetch(isbn)
↘
url = URL.format(isbn)
download(url)
↘
u = urlopen(url)
data = u.read()
return data
get_books() fetch() download()
────────────────────────────────────────────────
for isbn in books:
fetch(isbn)
↘
url = URL.format(isbn)
download(url)
↘
u = urlopen(url)
data = u.read()
return data:
# Best solution is Clean Architecture / Hexagonal
get_books() book_urls() build_url()
────────────────────────────────────────────────────
urls = book_urls(books)
for url in urls ↘
urlopen(url) for isbn in books:
data = u.read() yield build_url(isbn)
↘
u = URL.format(isbn)
return u
# Second best: patch() only the I/O
# get_books() → fetch() → download() → urlopen()
with patch('urlopen', ...):
get_books(['ISBN1', 'ISBN2'])
# Worst: disable immediate subroutine
# get_books() → fetch() → download() → urlopen()
args = []
with patch('fetch', args.append):
get_books(['ISBN1', 'ISBN2'])
assert args == ['ISBN1', 'ISBN2']
# my_module.py
def f():
for i in range(3):
print(i)
for letter in 'aąbcć':
print(letter)
my_package/
├ __init__.py ← people keeping putting code here
├ models.py
└ views.py
from threading import Thread
# Option 1
def task():
...
t = Thread(target=task)
t.start()
# Option 2
class MyThread(Thread):
def run(self):
...
t = MyThread()
t.start()
MSListWindow
MSIconWindow
MSImageWindow
MacListWindow
MacIconWindow
MacImageWindow
LinuxWindowListWindow
LinuxWindowIconWindow
LinuxWindowImageWindow
Window Layout
| |
MSWindow ListLayout
MacWindow IconLayout
LinuxWindow ImageLayout
# At runtime, two class instances
# are composed together
w = MacWindow()
return IconLayout(w)
layout(metrics, information)
↓
[Text, Text, Line,
Box, Line, Text]
↓
Window.render(graphics)
finish_request()
get_request()
handle_error()
handle_request()
handle_timeout()
process_request()
serve_forever()
server_activate()
server_bind()
server_close()
service_actions()
shutdown()
verify_request()
finish_request()
get_request()
handle_error()
handle_request()
handle_timeout()
process_request()
serve_forever() API
server_activate()
server_bind()
server_close() API
service_actions()
shutdown() API
verify_request()
finish_request()
get_request()
handle_error()
handle_request() A
handle_timeout()
process_request()
serve_forever() API
server_activate() A*
server_bind() A*
server_close() API
service_actions() A*
shutdown() API
verify_request()
finish_request()
get_request() B*
handle_error()
handle_request() A
handle_timeout()
process_request() B*
serve_forever() API
server_activate() A*
server_bind() A*
server_close() API
service_actions() A*
shutdown() API
verify_request() B*
finish_request() C
get_request() B*
handle_error()
handle_request() A
handle_timeout()
process_request() B*
serve_forever() API
server_activate() A*
server_bind() A*
server_close() API
service_actions() A*
shutdown() API
verify_request() B*
finish_request() C
get_request() B*
handle_error() D*
handle_request() A
handle_timeout() D*
process_request() B*
serve_forever() API
server_activate() A*
server_bind() A*
server_close() API
service_actions() A*
shutdown() API
verify_request() B*
finish_request() C
get_request() B*
handle_error() D*
handle_request() A
handle_timeout() D*
process_request() B*
serve_forever() API
server_activate() A*
server_bind() A*
server_close() API
service_actions() A*
shutdown() API
verify_request() B*
finish_request() C
get_request() B*
handle_error() D*
handle_request() A
handle_timeout() D*
process_request() B*
serve_forever() API
server_activate() A*
server_bind() A*
server_close() API
service_actions() A*
shutdown() API
verify_request() B*
Server Port Service
───────────────── ────────── ─────────────────
serve_forever() bind() service_actions()
process_request() activate() verify_request()
shutdown() get() handle_request()
close() handle_error()
handle_timeout()
↗ <Port> → <listening socket>
<Server>
↘ <Service>
# Mixin does not inherit from anything else
class ThreadingMixIn:
def process_request(self):
...
# By listing mixin first, its methods get
# priority over those of the other class
class MyService(ThreadingMixIn, BaseServer):
...
socketserver
┐ ┌
TCPServer │ │ ForkingMixIn
UDPServer │ × │ ThreadingMixIn
┘ └
class HybridDetailView(
JSONResponseMixin,
SingleObjectTemplateResponseMixin,
BaseDetailView
): ...