Informatika2-2014/teszt

A MathWikiből
(Változatok közti eltérés)
 
(egy szerkesztő 52 közbeeső változata nincs mutatva)
1. sor: 1. sor:
== a pythononline.org tesztelése ==
+
=== Dekorátor ===
  
Lássuk, hogy néz ki: példa a sekély másolásra:
+
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]]
  
<wikiframe width="800" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=x+%3D+%5B0,+%5B4,+5%5D,+3%5D%0Ay+%3D+x+++++++%23+hivatkoz%C3%A1s%0Az+%3D+x%5B%3A%5D++++%23+sek%C3%A9ly+m%C3%A1sol%C3%A1s+(shallow+copy)%0Ay%5B1%5D+%3D+1%0Az%5B1%5D+%3D+2%0Aprint+%22x+%3D%22,+x%0Aprint+%22y+%3D%22,+y%0Aprint+%22z+%3D%22,+z%0A&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=2&curInstr=0&codeDivWidth=350&codeDivHeight=400"> </wikiframe>
+
A '''dekorátorok''' módosítják függvények vagy osztályok kódját!
  
Idáig tart a beágyazás!
+
==== Scope (hatókör), névtér ====
  
<wikiframe width="800" height="500" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=def+lnko(a,+b)%3A%0A++++a,+b+%3D+abs(a),+abs(b)%0A++++while+a+!%3D+0%3A%0A++++++++a,+b+%3D+b+%25+a,+a%0A++++return+b%0A%0Aprint+lnko(-36,+8)%0Aprint+lnko(128,+9)&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=2&curInstr=0&codeDivWidth=350&codeDivHeight=400"> </wikiframe>
+
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:
  
Idáig meg a másik, minden átszerkesztés nélkül.
+
<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>
 +
 
 +
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>
 +
>>> def fn():
 +
...    y = 3
 +
...    print "x, y:", x, y
 +
...    print locals()
 +
...
 +
>>> fn()
 +
x, y: 2 3
 +
{'y': 3}
 +
</python>
 +
 
 +
Kérdés: Mi történik az alábbi kód hatására? magyarázzuk meg, mi történik:
 +
 
 +
<python>
 +
>>> def fn():
 +
...    y = 3
 +
...    print "x, y:", x, y
 +
...    x = 5
 +
...    print locals()
 +
...
 +
>>> fn()
 +
</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>
 +
>>> def fn():
 +
...    z = 1
 +
...
 +
>>> print z
 +
Traceback (most recent call last):
 +
  File "<stdin>", line 1, in <module>
 +
NameError: name 'z' is not defined
 +
</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>
 +
>>> def kulso(x):
 +
...    def belso():
 +
...        print x
 +
...    return belso
 +
...
 +
>>> f1 = kulso(3)
 +
>>> f2 = kulso(5)
 +
>>>
 +
>>> f1()
 +
3
 +
>>> f2()
 +
5
 +
</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>
 +
>>> 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
 +
</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>
 +
>>> @kulso
 +
... def fmul(a, b):
 +
...    return a * b
 +
...
 +
>>> fmul(3, 5)
 +
belül vagyunk
 +
30
 +
</python>
 +
 
 +
 
 +
Dekorátor lehet olyan osztály is, mely '''meghívható''', azaz amelyben létezik <code>__call__</code> függvény:
 +
 
 +
<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
 +
</python>

A lap jelenlegi, 2014. március 26., 10:29-kori változata

Dekorátor

Jó leírások: [[1]], [[2]]

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
Személyes eszközök