Informatika2-2014/teszt

A MathWikiből
(Változatok közti eltérés)
 
(egy szerkesztő 11 közbeeső változata nincs mutatva)
1. sor: 1. sor:
===OOP===
+
=== Dekorátor ===
  
[[http://docs.python.org/2/tutorial/classes.html]]
+
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]]
  
[[http://docs.python.org/2/library/operator.html]]
+
A '''dekorátorok''' módosítják függvények vagy osztályok kódját!
  
 +
==== Scope (hatókör), névtér ====
  
; Egységbezárás (encapsulation): a procedurális megközelítéssel ellentétben az adatok és a függvények a program nem különálló részét képezik, azok összetartoznak: együtt alkotnak egy objektumot. Az objektum felülete(ke)n (interfész, interface) keresztül érhető el a többi objektum számára.
+
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:
 
+
; Osztály (class): egy objektum prototípusa, tulajdonságokkal ellátva, melyek jellemzik az osztály példányait. A tulajdonságok osztály és példányváltozók, és metódusok (tagfüggvények). Pont-jelöléssel érhetők el.
+
 
+
; Attribútum/tulajdonság (attribute): egy objektum tulajdonsága, jellemzője, az objektum nevét követő pont után írjuk a nevét.
+
 
+
; Példány (instance): egy osztályhoz tartozó egyedi objektum.
+
 
+
; Példányosítás (instantiation): egy osztály egy példányának létrehozása.
+
 
+
; Példány változó (instance variable): metóduson belül definiált változó, mely csak az osztály adott példányához tartozik.
+
 
+
; Osztályváltozó (class variable): változó, melyet az osztály minden példánya elér.
+
 
+
; Metódus (method, tagfüggvény): osztályon belül definiált spec. függvény, első argumentuma tipikusan a self.
+
 
+
; Öröklődés (inheritance): származtatással egy már meglévő osztályból egy újat hozunk létre. Ez rendelkezni fog az ős minden tulajdonságával, amihez továbbiakat ad(hat)unk.
+
 
+
; Polimorfizmus/többalakúság (polymorphism): különböző viselkedésmódokkal ruházzuk fel az egymásból származtatott objektumokat.
+
 
+
; Névtér (namespace): megadja, hogy egy név melyik objektumhoz tartozik (leképezés a nevekről az objektumokra). (Példák névterekre: foglalt nevek, globális változók, egy függvény lokális nevei).
+
 
+
; Hatókör/szkóp (scope): a kód azon része, ahol a névtér közvetlenül (a teljes elérési út magadása nélkül) elérhető.
+
  
 
<python>
 
<python>
>>> class Osztalyom:
+
>>> x = 2
...    "Egy egyszerű példa osztályra"
+
>>> print globals()
...    i = 123
+
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'x': 2, '__doc__': None, '__package__': None}
...    def f(self, i):
+
>>> def fn():
...         self.i = i
+
...     y = 3
...         return 'hello vilag'
+
...     print locals()
 
...  
 
...  
>>> x = Osztalyom()
+
>>> fn()
>>> x.i
+
{'y': 3}
123
+
>>> x.f(5)
+
'hello vilag'
+
>>> x.i
+
5
+
>>> Osztalyom.i
+
123
+
 
</python>
 
</python>
  
Objektum '''kívülről''' ráaggatott attribútumokkal (ritkán van erre szükség):
+
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>
>>> x.szamlalo = 1
+
>>> def fn():
>>> while x.szamlalo < 10:
+
...    y = 3
...    x.szamlalo = x.szamlalo * 2
+
...    print "x, y:", x, y
 +
...    print locals()
 
...  
 
...  
>>> print x.szamlalo
+
>>> fn()
16
+
x, y: 2 3
>>> del x.szamlalo
+
{'y': 3}
 
</python>
 
</python>
  
Konstruktor <code>__init__</code>
+
Kérdés: Mi történik az alábbi kód hatására? magyarázzuk meg, mi történik:
  
 
<python>
 
<python>
class Komplex:
+
>>> def fn():
 
+
...    y = 3
    def __init__(self, real, imag):
+
...    print "x, y:", x, y
        self.r = real
+
...    x = 5
        self.i = imag
+
...     print locals()
       
+
...
     def konjugalt(self):
+
>>> fn()
        return Komplex(self.r, -self.i)
+
 
</python>
 
</python>
  
Használatára létrejön egy példány, melynek memóriacímét kapjuk vissza nevének beírása után:
+
És mi történik, ha a 3. és 4. sort fölcseréljük?
  
<python>
+
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:
>>> z = Komplex(3, 4)
+
>>> z
+
<__main__.Komplex instance at 0x184a710>
+
>>> w = z.konjugalt()
+
>>> w
+
<__main__.Komplex instance at 0x184a758>
+
</python>
+
 
+
Tulajdonságaik lekérdezhetők:
+
  
 
<python>
 
<python>
>>> z.r, z.i
+
>>> def fn():
(3, 4)
+
...    z = 1
>>> w.r, w.i
+
...  
(3, -4)
+
>>> print z
 +
Traceback (most recent call last):
 +
  File "<stdin>", line 1, in <module>
 +
NameError: name 'z' is not defined
 
</python>
 
</python>
  
További tulajdonságokkal ruházzuk fel a Komplex osztály objektumait. Ehhez a speciális metódusokat használjuk:
+
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>
class Komplex:
+
>>> def kulso(x):
    """Komplex számok kezelése."""
+
...     def belso():
+
...         print x
     def __init__(self, real, imag):
+
...     return belso
         """Komplex szám létrehozása"""
+
...
        self.r = real
+
>>> f1 = kulso(3)
        self.i = imag
+
>>> f2 = kulso(5)
   
+
>>>
     def konjugalt(self):
+
>>> f1()
        return Komplex(self.r, -self.i)
+
3
   
+
>>> f2()
    def __add__(self, z):
+
5
        """Az infix '+' művelet használatához."""
+
        return Komplex(self.r + z.r, self.i + z.i)
+
   
+
    def __repr__(self):
+
        """Komplex szám megjelenése interaktív módban.
+
        Ugyanezt kapjuk a print parancsra is."""
+
+
        # ez egyelőre rossz, mert a 3 - 4i képe ez lesz: 3 + -4i
+
        return repr(self.r) + " + " + repr(self.i) + "i"
+
 
</python>
 
</python>
  
Alkalmazása:
+
==== Dekorálunk ====
  
<python>
+
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!
>>> z1 = Komplex(3, 4)
+
>>> z2 = Komplex(1, 5)
+
>>> z1 + z2
+
4 + 9i
+
>>> z1
+
3 + 4i
+
>>> z2
+
1 + 5i
+
>>> z1 + z2
+
4 + 9i
+
</python>
+
  
 
<python>
 
<python>
>>> type(z1)
+
>>> def kulso(fn):
<type 'instance'>
+
...    def belso(*args):
>>> isinstance(z1, Komplex)
+
...        print "belül vagyunk"
True
+
...        return 2*fn(*args)
>>> z1.__class__
+
...    return belso
<class __main__.Komplex at 0x21ce3f8>
+
...
>>> z1.__module__
+
>>> dekoralt = kulso(fv)
'__main__'
+
>>> dekoralt(5)
>>> z1.__class__.__name__
+
belül vagyunk
'Komplex'
+
10
>>> dir(z1)
+
>>> def fadd(a, b):
['__add__', '__doc__', '__init__', '__module__', '__repr__', 'i', 'konjugalt', 'r']
+
...    return a + b
>>> print z1.__doc__
+
...  
Komplex számok kezelése.
+
>>> dekoralt = kulso(fadd)
>>> z1.konjugalt()
+
>>> dekoralt(4, 5)
3 + -4i
+
belül vagyunk
>>> z1.__add__(z2)
+
18
4 + 9i
+
 
</python>
 
</python>
  
Egy példa az osztályváltozó alkalmazására:
+
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>
class Alkalmazott:
+
>>> @kulso
    """Alkalmazottak osztálya"""
+
... def fmul(a, b):
    alkSzamlalo = 0
+
...     return a * b
 
+
...  
    def __init__(self, nev, fizetes):
+
>>> fmul(3, 5)
        """Konstruktor az alkalmazottaknak"""
+
belül vagyunk
 
+
30
        self.nev = nev
+
        self.fizetes = fizetes
+
        Alkalmazott.alkSzamlalo += 1
+
        self.sorszam = Alkalmazott.alkSzamlalo
+
   
+
    def szamlalot_kiir(self):
+
        mit = "{0} a {1}. alkalmazott az összesen {2} között"
+
        print mit.format(self.nev, self.sorszam, Alkalmazott.alkSzamlalo)
+
 
+
    def adatot_kiir(self):
+
        print "Név: ", self.nev,  ", Fizetés: ", self.fizetes
+
 
</python>
 
</python>
  
<python>
 
>>> a1 = Alkalmazott("Jóska", 1000000)
 
>>> a2 = Alkalmazott("Pista", 200000)
 
>>> a3 = Alkalmazott("Ildikó", 2000000)
 
>>> a2.szamlalot_kiir()
 
Pista a 2. alkalmazott az összesen 3 között
 
>>> a2.adatot_kiir()
 
Név:  Pista , Fizetés:  200000
 
>>> a3.adatot_kiir()
 
Név:  Ildikó , Fizetés:  2000000
 
</python>
 
  
Példa az öröklésre. Szülő osztály:
+
Dekorátor lehet olyan osztály is, mely '''meghívható''', azaz amelyben létezik <code>__call__</code> függvény:
  
 
<python>
 
<python>
class Ellipszis:
+
>>> class Dekorator(object):
 
+
...     def __init__(self, f):
     def __init__(self, kozeppont, felx, fely):
+
...        print "Dekorátor konstruktor"
        self.kozeppont = kozeppont
+
...         print "meghívjuk a fv-t:", f()
        self.felx = felx
+
...     def __call__(self):
        self.fely = fely
+
...         print "Dekorátor meghívása"
          
+
...  
    def terulete(self):
+
>>> @Dekorator
        return self.felx*self.fely*3.14159
+
... def fn():
</python>
+
...     print "az fn meghívása"
 
+
...  
Gyerek osztály:
+
Dekorátor konstruktor
 
+
meghívjuk a fv-t: az fn meghívása
<python>
+
None
class Kor(Ellipszis):
+
>>> fn()
 
+
Dekorátor meghívása
     def __init__(self, kozeppont, sugar):
+
         Ellipszis.__init__(self, kozeppont, sugar, sugar)
+
        self.sugar = sugar
+
</python>
+
 
+
<python>
+
>>> e = Ellipszis((0, 0), 3, 2)
+
>>> e.felx
+
3
+
>>> e.fely
+
2
+
>>> e.terulete()
+
18.849539999999998
+
>>> k = Kor((2, 0), 3)
+
>>> k.felx
+
3
+
>>> k.fely
+
3
+
>>> k.sugar
+
3
+
>>> k.terulete()
+
28.27431
+
</python>
+
 
+
Függvény felülírása:
+
 
+
<python>
+
class Kor(Ellipszis):
+
 
+
    def __init__(self, kozeppont, sugar):
+
        Ellipszis.__init__(self, kozeppont, sugar, sugar)
+
        self.sugar = sugar
+
 
+
    def terulete(self):
+
        return self.sugar**2*3.14159
+
 
</python>
 
</python>

A lap jelenlegi, 2014. március 26., 09: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