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()
© Copyright 2024 ExpyDoc