def

Python-indoctrinatie
Stijn & Felix
Zeker dat je wil blijven?
Zeker dat je wil blijven?
3.4
Overview
●
●
●
●
●
●
(nu kan je niet meer weglopen)
Generators
Functioneel programmeren
Everything is a reference
Decorators
Magic methods
Context managers
Iteratoren
Iteratoren
class MyIterator:
def __iter__(self):
return self
def __next__(self):
pass
Iteratoren
class MyRange:
def __init__(self):
self.current = 0
def __iter__(self):
return self
def __next__(self):
self.current += 1
return current
Iterator voor tree traversal
Enter generators
def f():
yield ‘a’
yield ‘b’
yield ‘c’
>>> for x in f():
...
print(x)
...
a
b
c
Generator als iterator
Subgenerators
“yield from subgenerator”
Generator expressions
● Stel, je wilt een som van kwadraten
Generator expressions
● Stel, je wilt een som van kwadraten
● One-liners i.p.v. expliciete for-lussen
● Lazy evaluation i.p.v. in-memory lijst
● Vooral handig bij reduce-functies
○ sum, all/any, in, min/max
Itertools
Volgende week
Overview
●
●
●
●
●
●
(nu kan je niet meer weglopen)
Generators
Functioneel programmeren
Everything is a reference
Decorators
Magic methods
Context managers
Functioneel programmeren
● Geen toestand bijhouden
Functioneel programmeren
● Geen toestand bijhouden
● Niet puur functioneel
Functioneel programmeren
● Geen toestand bijhouden
● Niet puur functioneel
○ Lokale variabelen zijn OK
Functioneel programmeren
● Geen toestand bijhouden
● Niet puur functioneel
○ Lokale variabelen zijn OK
● Lazy evaluation
Functioneel programmeren
● Geen toestand bijhouden
● Niet puur functioneel
○ Lokale variabelen zijn OK
● Lazy evaluation
● Higher-order programming
○ functies als first-class citizens
Functioneel programmeren
● Geen toestand bijhouden
● Niet puur functioneel
○ Lokale variabelen zijn OK
● Lazy evaluation
● Higher-order programming
○ functies als first-class citizens
● Currying
Functioneel programmeren
●
●
●
●
●
Generators
Generator chaining
Map, filter, reduce
Lambda’s
Partials
Generator chaining
a = (f(x) for x in xs)
b = (g(x) for x in a)
Lambda’s
def f(x):
return x ** x
f = lambda x: x ** x
Map
map(func, xs)
map(lambda x: …, xs)
Map / filter
map(func, xs)
map(lambda x: …, xs)
filter(cond, xs)
filter(lambda x: …, xs)
Comprehensions
map(func, xs)
Comprehensions
map(func, xs)
== (func(x) for x in xs)
Comprehensions
map(func, xs)
== (func(x) for x in xs)
Comprehensions
map(func, xs)
== (func(x) for x in xs)
filter(cond, xs)
== (x for x in xs if cond(x))
Functools
● partials
● reduce
Functools: Currying
● functools.partial(func, *args, **kwargs)
Functools: Currying
● functools.partial(func, *args, **kwargs)
● increment = partial(operator.add, 1)
● >>> increment(5)
6
Functools: Reduce
● functools.reduce(func,
iterable[,
initializer])
Functools: Reduce
● functools.reduce(func,
iterable[,
initializer])
● sum(xs) == reduce(operator.add, xs, 0)
Overview
●
●
●
●
●
●
(nu kan je niet meer weglopen)
Generators
Functioneel programmeren
Everything is a reference
Decorators
Magic methods
Context managers
Everything is a reference
● Function as first-class citizens
Everything is a reference
● Function as first-class citizens
● Classes as first-class citizens
Everything is a reference
● Function as first-class citizens
● Classes as first-class citizens
● Modules as first-class citizens
Pointer aliasing
x = [1, 2, 3]
x.append(x)
>>> x
Pointer aliasing
x = [1, 2, 3]
x.append(x)
>>> x
[1, 2, 3, [...]]
Pointer aliasing
xs = 5 * [[]]
xs[0].append(‘a’)
>>> xs
Pointer aliasing
xs = 5 * [[]]
xs[0].append(‘a’)
>>> xs
[['a'], ['a'], ['a'], ['a'], ['a']]
Default arguments
def f(x=[]):
x.append(1)
return x
>>> f()
[1]
Default arguments
def f(x=[]):
x.append(1)
return x
>>> f()
[1]
>>> f([3,2])
[3,2,1]
Default arguments
def f(x=[]):
x.append(1)
return x
>>> f()
[1]
>>> f([3,2])
[3,2,1]
>>> f()
Default arguments
def f(x=None):
if x is None:
x = []
x.append(1)
return x
>>> f()
[1]
>>> f([3,2])
[3,2,1]
>>> f()
Closures
def f(x):
def g(y):
return x + y
return g
>>> add_5 = f(5)
>>> add_5(3)
8
Wrappers
def add_one(f):
def g(*args, **kw):
return f(*args, **kw) + 1
return g
Wrappers
def add_one(f):
def g(*args, **kw):
return f(*args, **kw) + 1
return g
def h(x):
return x + 2
Wrappers
def add_one(f):
def g(*args, **kw):
return f(*args, **kw) + 1
return g
def h(x):
return x + 2
h = add_one(h)
Overview
●
●
●
●
●
●
(nu kan je niet meer weglopen)
Generators
Functioneel programmeren
Everything is a reference
Decorators
Magic methods
Context managers
Wrappers
def wrapper(f):
def g(*args, **kw):
...
return g
def h(x):
...
h = wrapper(h)
Decorators
def wrapper(f):
def g(*args, **kw):
...
return g
@wrapper
def h(x):
...
Decorators
def wrapper(f):
def g(*args, **kw):
...
return g
@wrapper
def h(x):
...
@staticmethod
@classmethod
class A:
...
@staticmethod
def f():
...
class A:
...
@staticmethod
def f():
...
class A:
...
def f():
...
Fibonacci
def fibo(n):
if n <= 1:
return 1
return fibo(n-1) + fibo(n-2)
Memoization
@functools.lru_cache
def fibo(n):
if n <= 1:
return 1
return fibo(n-1) + fibo(n-2)
class Country:
...
def __lt__(self, other):
return self.name < other.name
def __eq__(self, other):
return self.name == other.name
Class decorators
@functools.total_ordering
class Country:
...
def __lt__(self, other):
return self.name < other.name
def __eq__(self, other):
return self.name == other.name
Typechecking
@require(x=int, y=str, z=float)
def f(x, y, z):
...
Flask web framework
@route(‘/’)
def home():
...
@route(‘/page1’)
def page1():
...
Overview
●
●
●
●
●
●
(nu kan je niet meer weglopen)
Generators
Functioneel programmeren
Everything is a reference
Decorators
Magic methods
Context managers
Magic methods
● Methoden die interageren
met builtin features
Iterators
x = iter(an_iterable)
iterable.__iter__()
next(x)
next(x)
iterator.__next__()
Magic methods: vergelijkingen
a
a
a
a
a
a
< b
<= b
> b
>= b
== b
!= b
a.__lt__(b)
a.__le__(b)
a.__gt__(b)
a.__ge__(b)
a.__eq__(b)
a.__ne__(b)
Magic methods: operatoren
__add__, __sub__, __mul__,
__truediv__, __floordiv__, __mod__,
__divmod__, __pow__, __lshift__,
__rshift__, __and__, __xor__,
__or__, __neg__, __pos__, __abs__,
__invert__, __complex__, __int__,
__float__, __round__, __index__
Magic methods: info
__doc__, __name__, __module__,
__code__, __defaults__,
__kwdefaults__, __globals__,
__dict__, __closure__, __bases__,
__class__, __sizeof__, __dir__
Overrideable methods
hash(x)
bytes(x)
“{}”.format(x)
if x: ...
x()
len(x)
x.__hash__()
x.__bytes__()
x.__format__(“{}”)
x.__bool__()
x.__call__()
x.__len__()
Instance customization
__init__(self, …)
__new__(cls, …)
__del__(self)
Type conversion
int(a)
long(a)
float(a)
complex(a)
oct(a)
hex(a)
a.__int__()
a.__long__()
a.__float__()
a.__complex__()
a.__oct__()
a.__hex__()
Stringification
str(a)
print(a)
a.__str__()
repr(a)
a.__repr__()
Containers
a[key]
a[key] = value
del a[key]
item in a
reversed(a)
a[non_key]
a.__getitem__(key)
a.__setitem__(key, value)
a.__delitem__(key)
a.__contains__(item)
a.__reversed__()
a.__missing__(non_key)
Managed attributes
Descriptors
Vast aantal attributen
class A:
__slots__ = [‘x’, ‘y’]
Volgende week
__annotations__
__reduce__
__reduce_ex__
Overview
●
●
●
●
●
●
(nu kan je niet meer weglopen)
Generators
Functioneel programmeren
Everything is a reference
Decorators
Magic methods
Context managers
Context managers
with open(file_name) as some_file:
do_stuff_with(some_file)
Context managers
with ... as ...:
...
Context managers
with A(...) as ...:
...
Context managers
class A:
def __enter__(self, args):
with A(args) as ...:
open_something(args)
...
def __exit__(self):
close_something
Context managers
import contextlib
with f(args) as ...:
...
@contextlib.contextmanager
def f(args):
open_something()
yield
close_something()