Github Com Austin Taylor Code Vault Blob Master Python Expert Notebook Ipynb
Github Com Austin Taylor Code Vault Blob Master Python Expert Notebook Ipynb
Dismiss
Join GitHub today
GitHub is home to over 28 million developers working together to host and
review code, manage projects, and build software together.
Sign up
2 contributors
If you want to become an expert in Python, you should definitely watch this PyData talk from James Powell.
Video Index
metaclasses: 18:50
metaclasses(explained): 40:40
decorator: 45:20
generator: 1:04:30
context manager: 1:22:37
summary: 1:40:00
Definitions Python is a language orientated around protocols - Some behavior or syntax or bytecode or some top level function and
there is a way to tell python how to implement that on an arbitrary object via underscore methods. The exact correspondance is
usually guessable, but if you can't guess it you can it... google python data model
Metaclass Mechanism: Some hook into the class construction process. Questions: Do you have these methods implemented.
Meaning: Library code & User code? How do you enforce a constraint?
Decorator Hooks into idea that everything creates a structure at run time. Wrap sets of functions with a before and after behavior.
Generators Take a single computation that would otherwise run eagerly from the injection of its parameters to the final computation
and interleaving with other code by adding yield points where you can yield the intermediate result values or one small piece of the
computation and also yield back to the caller. Think of a generator of a way to take one long piece of computation and break it up
into small parts.
Context managers Two structures that allow you to tie two actions together. A setup action and a teardown action and make sure
they always happen in concordance with each other.
In [7]: # some behavior that I want to implement -> write some __ function __
# top-level function or top-level syntax -> corresponding __
# x + y -> __add__
# init x -> __init__
# repr(x) --> __repr__
# x() -> __call__
class Polynomial:
def __init__(self, *coeffs):
self.coeffs = coeffs
def __repr__(self):
return 'Polynomial(*{!r})'.format(self.coeffs)
def __len__(self):
return len(self.coeffs)
def __call__(self):
pass
In [8]: p1 = Polynomial(1, 2, 3)
p2 = Polynomial(3, 4, 3)
In [9]: p1 + p2
Out[10]: 3
Metaclasses
In [26]: # File 1 - library.py
class Base:
def food(self):
return 'foo'
class Derived(Base):
def bar(self):
return self.foo
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-27-08fa6af0fb76> in <module>()
1 # File2 - user.py
2
----> 3 assert hasattr(Base, 'foo'), "you broke it, you fool!"
4
5 class Derived(Base):
class Base:
def foo(self):
return self.bar()
class Derived(Base):
def bar(self):
return 'bar'
In [45]: Derived.bar
2 0 LOAD_BUILD_CLASS
2 LOAD_CONST 1 (<code object Base at 0x10f2daed0, file "<ipython-inpu
t-18-a194b247271c>", line 2>)
4 LOAD_CONST 2 ('Base')
6 MAKE_FUNCTION 0
8 LOAD_CONST 2 ('Base')
10 CALL_FUNCTION 2
12 STORE_FAST 0 (Base)
14 LOAD_CONST 0 (None)
16 RETURN_VALUE
class Base:
def foo(self):
return self.bar()
old_bc = __build_class__
def my bc(*a **kw):
def my_bc(*a, **kw):
print('my buildclass ->', a, kw)
return old_bc(*a, **kw)
import builtins
builtins.__build_class__ = my_bc
class Base:
def foo(self):
return self.bar()
old_bc = __build_class__
def my_bc(fun, name, base=None, **kw):
if base is Base:
print('Check if bar method defined')
if base is not None:
return old_bc(fun, name, base, **kw)
return old_bc(fun, name, **kw)
import builtins
builtins.__build_class__ = my_bc
class Base(metaclass=BaseMeta):
def foo(self):
return self.bar()
class Base(metaclass=BaseMeta):
def foo(self):
return self.bar()
class Base(metaclass=BaseMeta):
def foo(self):
return self.bar()
In [8]: help(Base.__init_subclass__)
Decorators
In [12]: # dec.py
Out[14]: 30
In [15]: add
Out[28]: 'add'
Out[27]: '__main__'
Out[26]: (10,)
Out[25]: b'|\x00|\x01\x17\x00S\x00'
In [32]: getsource(add)
In [33]: print(getsource(add))
Out[35]: '<ipython-input-19-3cec442ba064>'
add(10) 20
add(20, 30) 50
add("a", "b") ab
elapsed: 0.0
add(10) 20
elapsed: 9.5367431640625e-07
add(20, 30) 50
elapsed: 9.5367431640625e-07
add("a", "b") ab
sub(10) 0
sub(20, 30) -10
elapsed 9.5367431640625e-07
add(10) 20
elapsed 9.5367431640625e-07
add(20, 30) 50
elapsed 9.5367431640625e-07
add("a", "b") ab
elapsed 9.5367431640625e-07
add(10) 20
elapsed 9.5367431640625e-07
add(20, 30) 50
elapsed 9.5367431640625e-07
add("a", "b") ab
In [87]: @timer
def add_dec(x, y=10):
return x + y
@timer
def sub_dec(x, y=10):
return x - y
elapsed 9.5367431640625e-07
add(10) 20
elapsed 1.1920928955078125e-06
add(20, 30) 50
elapsed 1.1920928955078125e-06
add("a", "b") ab
elapsed 9.5367431640625e-07
sub(10) 0
elapsed 0.0
sub(20, 30) -10
In [92]: @timer_k
def add_dec(x, y=10):
return x + y
@timer_k
def sub_dec(x, y=10):
return x - y
print('add(10)', add_dec(10))
print('add(20, 30)', add_dec(20, 30))
print('add("a", "b")', add_dec("a", "b"))
print('sub(10)' sub dec(10))
print( sub(10) , sub_dec(10))
print('sub(20, 30)', sub_dec(20, 30))
elapsed 9.5367431640625e-07
add(10) 20
elapsed 9.5367431640625e-07
add(20, 30) 50
elapsed 9.5367431640625e-07
add("a", "b") ab
elapsed 0.0
sub(10) 0
elapsed 9.5367431640625e-07
sub(20, 30) -10
In [94]: # Let's have add run 3 times in a row and sub run twice in a row
In [97]: n = 2
def ntimes(f):
def wrapper(*args, **kwargs):
for _ in range(n):
print('running {.__name__}'.format(f))
rv = f(*args, **kwargs)
return rv
return wrapper
@ntimes
def add_dec(x, y=10):
return x + y
@ntimes
def sub_dec(x, y=10):
return x - y
running add_dec
running add_dec
add(10) 20
running add_dec
running add_dec
add(20, 30) 50
running add_dec
running add_dec
add("a", "b") ab
running sub_dec
running sub_dec
sub(10) 0
running sub_dec
running sub_dec
sub(20, 30) -10
@ntimes(2)
def add_hdec(x, y=10):
return x + y
@ntimes(4)
d f b hd ( 0)
def sub_hdec(x, y=10):
return x - y
running add_hdec
running add_hdec
add(10) 20
running add_hdec
running add_hdec
add(20, 30) 50
running add_hdec
running add_hdec
add("a", "b") ab
running sub_hdec
running sub_hdec
running sub_hdec
running sub_hdec
sub(10) 0
running sub_hdec
running sub_hdec
running sub_hdec
running sub_hdec
sub(20, 30) -10
Generators
In [105]: # gen.py - use whenever sequencing is needd
class Adder:
def __call__(self, x, y):
return x + y
add2 = Adder()
Out[110]: 30
Out[111]: 30
class Adder:
def __init__(self):
self.z = 0
add2 = Adder()
In [120]: compute()
Out[120]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Wasteful because we have to wait for the entire action to complete and be read into memory, when we really just care about each
number (one by one)
def __iter__(self):
self.last = 0
return self
def __next__(self):
rv = self.last
self.last += 1
if self.last > 10:
raise StopIteration()
sleep(.5)
return self.last
compute = Compute()
In [131]: #This is a generator... don't eagerly compute. Return to user as they ask for it...
def compute():
for i in range(10):
sleep(.5)
yield i
0
1
2
3
4
5
6
7
8
9
# x = ctx().__enter__
# try:
# pass
# finally:
# x.__exit__
class temptable:
def __init__(self, cur):
self.cur = cur
def __enter__(self):
print('__enter__')
self.cur.execute('create table points(x int, y int)')
def __exit__(self, *args):
print('__exit__')
self.cur.execute('drop table points')
__enter__
(1, 1)
(1, 2)
(2, 1)
(2, 2)
(9,)
__exit__
In [162]: rm test.db
class contextmanager:
def __init__(self, cur):
self.cur = cur
def __enter__(self):
self.gen = temptable(self.cur)
next(self.gen)
def __exit__(self, *args):
next(self.gen, None)
created table
(1, 1)
( 2)
(1, 2)
(2, 1)
(2, 2)
(9,)
dropped table
def temptable(cur):
cur.execute('create table points(x int, y int)')
print('created table')
yield
cur.execute('drop table points')
print('dropped table')
temptable = contextmanager(temptable)
created table
(1, 1)
(1, 2)
(2, 1)
(2, 2)
dropped table
@contextmanager
def temptable(cur):
cur.execute('create table points(x int, y int)')
print('created table')
yield
cur.execute('drop table points')
print('dropped table')
created table
(1, 1)
(1, 2)
(2, 1)
(2, 2)
dropped table
In [15]: from sqlite3 import connect
from contextlib import contextmanager
@contextmanager
def temptable(cur):
cur.execute('create table points(x int, y int)')
print('created table')
try:
yield
finally:
cur.execute('drop table points')
print('dropped table')
created table
(1, 1)
(1, 2)
(2, 1)
(2, 2)
dropped table
© 2018 GitHub, Inc. Terms Privacy Security Status Help Contact GitHub Pricing API Training Blog About