Informatika2-2014/teszt
(egy szerkesztő 7 közbeeső változata nincs mutatva) | |||
1. sor: | 1. sor: | ||
− | === | + | === Dekorátor === |
− | [[http:// | + | Jó leírások: [[http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/]], [[http://www.artima.com/weblogs/viewpost.jsp?thread=240808]] |
− | + | A '''dekorátorok''' módosítják függvények vagy osztályok kódját! | |
+ | ==== Scope (hatókör), névtér ==== | ||
− | + | Minden új függvény fölépíti saját névterét, egy szótár formájában. Íme a globális és egy lokális névtér: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
<python> | <python> | ||
− | >>> | + | >>> x = 2 |
− | + | >>> print globals() | |
− | + | {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'x': 2, '__doc__': None, '__package__': None} | |
− | + | >>> def fn(): | |
− | ... | + | ... y = 3 |
− | ... | + | ... print locals() |
... | ... | ||
− | >>> | + | >>> fn() |
− | + | {'y': 3} | |
− | + | ||
− | + | ||
− | ' | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
</python> | </python> | ||
− | + | Ha egy név lokálisan nem lett létrehozva, a tartalmazó névterekben keresi egyre kijjebb haladva (itt az x nem lett lokálisan létrehozva, de elérhető): | |
<python> | <python> | ||
− | >>> | + | >>> def fn(): |
− | + | ... y = 3 | |
− | ... x | + | ... print "x, y:", x, y |
+ | ... print locals() | ||
... | ... | ||
− | >>> | + | >>> fn() |
− | + | x, y: 2 3 | |
− | + | {'y': 3} | |
</python> | </python> | ||
− | + | Kérdés: Mi történik az alábbi kód hatására? magyarázzuk meg, mi történik: | |
<python> | <python> | ||
− | + | >>> def fn(): | |
− | + | ... y = 3 | |
− | + | ... print "x, y:", x, y | |
− | + | ... x = 5 | |
− | + | ... print locals() | |
− | + | ... | |
− | + | >>> fn() | |
− | + | ||
</python> | </python> | ||
− | + | És mi történik, ha a 3. és 4. sort fölcseréljük? | |
− | + | A névtér törlődik a függvény lefutása után, magasabb szinten az alacsonyabb szintű névterek nem érhetők el: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
<python> | <python> | ||
− | >>> | + | >>> def fn(): |
− | + | ... z = 1 | |
− | >>> | + | ... |
− | ( | + | >>> print z |
+ | Traceback (most recent call last): | ||
+ | File "<stdin>", line 1, in <module> | ||
+ | NameError: name 'z' is not defined | ||
</python> | </python> | ||
− | + | A '''függvény lezárása''' a Pythonnak azt a képességét jelenti, hogy a nem globális névtérben definiált függvény '''emlékszik''' a definiálás pillanatában érvényes bennfoglaló névterekre: | |
<python> | <python> | ||
− | + | >>> def kulso(x): | |
− | + | ... def belso(): | |
− | + | ... print x | |
− | + | ... return belso | |
− | + | ... | |
− | + | >>> f1 = kulso(3) | |
− | + | >>> f2 = kulso(5) | |
− | + | >>> | |
− | + | >>> f1() | |
− | + | ||
− | + | ||
− | def | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | >>> | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | >>> | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | >> | + | |
− | + | ||
3 | 3 | ||
− | >>> | + | >>> f2() |
− | + | 5 | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
</python> | </python> | ||
− | + | ==== Dekorálunk ==== | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
+ | A külső függvény az argumentumában átadott függvény eredményét duplázza, és ezt a duplázó függvényt adja vissza. Ezzel '''dekorálunk''' két különböző függvényt! | ||
<python> | <python> | ||
− | + | >>> def kulso(fn): | |
− | + | ... def belso(*args): | |
− | def | + | ... print "belül vagyunk" |
− | + | ... return 2*fn(*args) | |
− | + | ... return belso | |
− | + | ... | |
− | + | >>> dekoralt = kulso(fv) | |
− | + | >>> dekoralt(5) | |
+ | belül vagyunk | ||
+ | 10 | ||
+ | >>> def fadd(a, b): | ||
+ | ... return a + b | ||
+ | ... | ||
+ | >>> dekoralt = kulso(fadd) | ||
+ | >>> dekoralt(4, 5) | ||
+ | belül vagyunk | ||
+ | 18 | ||
</python> | </python> | ||
− | < | + | A <code>fv = kulso(fv)</code> rövidítése a <code>@kulso</code> a fv függvénydefiníció elé írásával: |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | </ | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
<python> | <python> | ||
− | >>> | + | >>> @kulso |
− | + | ... def fmul(a, b): | |
− | + | ... return a * b | |
− | + | ... | |
− | >>> | + | >>> fmul(3, 5) |
− | + | belül vagyunk | |
− | + | 30 | |
− | + | ||
− | + | ||
− | 3 | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
</python> | </python> | ||
− | |||
− | |||
− | |||
− | + | Dekorátor lehet olyan osztály is, mely '''meghívható''', azaz amelyben létezik <code>__call__</code> függvény: | |
− | + | ||
− | </ | + | |
<python> | <python> | ||
− | >>> | + | >>> class Dekorator(object): |
− | + | ... def __init__(self, f): | |
− | + | ... print "Dekorátor konstruktor" | |
− | + | ... print "meghívjuk a fv-t:", f() | |
− | + | ... def __call__(self): | |
− | + | ... print "Dekorátor meghívása" | |
− | + | ... | |
− | + | >>> @Dekorator | |
− | + | ... def fn(): | |
− | + | ... print "az fn meghívása" | |
− | + | ... | |
− | + | Dekorátor konstruktor | |
− | + | meghívjuk a fv-t: az fn meghívása | |
− | + | None | |
− | + | >>> fn() | |
− | + | Dekorátor meghívása | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | def | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | print " | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | > | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | >>> | + | |
− | + | ||
− | + | ||
− | + | ||
</python> | </python> |
A lap jelenlegi, 2014. március 26., 10:29-kori változata
Dekorátor
A dekorátorok módosítják függvények vagy osztályok kódját!
Scope (hatókör), névtér
Minden új függvény fölépíti saját névterét, egy szótár formájában. Íme a globális és egy lokális névtér:
>>> x = 2 >>> print globals() {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'x': 2, '__doc__': None, '__package__': None} >>> def fn(): ... y = 3 ... print locals() ... >>> fn() {'y': 3}
Ha egy név lokálisan nem lett létrehozva, a tartalmazó névterekben keresi egyre kijjebb haladva (itt az x nem lett lokálisan létrehozva, de elérhető):
>>> def fn(): ... y = 3 ... print "x, y:", x, y ... print locals() ... >>> fn() x, y: 2 3 {'y': 3}
Kérdés: Mi történik az alábbi kód hatására? magyarázzuk meg, mi történik:
>>> def fn(): ... y = 3 ... print "x, y:", x, y ... x = 5 ... print locals() ... >>> fn()
És mi történik, ha a 3. és 4. sort fölcseréljük?
A névtér törlődik a függvény lefutása után, magasabb szinten az alacsonyabb szintű névterek nem érhetők el:
>>> def fn(): ... z = 1 ... >>> print z Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'z' is not defined
A függvény lezárása a Pythonnak azt a képességét jelenti, hogy a nem globális névtérben definiált függvény emlékszik a definiálás pillanatában érvényes bennfoglaló névterekre:
>>> def kulso(x): ... def belso(): ... print x ... return belso ... >>> f1 = kulso(3) >>> f2 = kulso(5) >>> >>> f1() 3 >>> f2() 5
Dekorálunk
A külső függvény az argumentumában átadott függvény eredményét duplázza, és ezt a duplázó függvényt adja vissza. Ezzel dekorálunk két különböző függvényt!
>>> def kulso(fn): ... def belso(*args): ... print "belül vagyunk" ... return 2*fn(*args) ... return belso ... >>> dekoralt = kulso(fv) >>> dekoralt(5) belül vagyunk 10 >>> def fadd(a, b): ... return a + b ... >>> dekoralt = kulso(fadd) >>> dekoralt(4, 5) belül vagyunk 18
A fv = kulso(fv)
rövidítése a @kulso
a fv függvénydefiníció elé írásával:
>>> @kulso ... def fmul(a, b): ... return a * b ... >>> fmul(3, 5) belül vagyunk 30
Dekorátor lehet olyan osztály is, mely meghívható, azaz amelyben létezik __call__
függvény:
>>> class Dekorator(object): ... def __init__(self, f): ... print "Dekorátor konstruktor" ... print "meghívjuk a fv-t:", f() ... def __call__(self): ... print "Dekorátor meghívása" ... >>> @Dekorator ... def fn(): ... print "az fn meghívása" ... Dekorátor konstruktor meghívjuk a fv-t: az fn meghívása None >>> fn() Dekorátor meghívása