|
|
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:
| |
| | | |
| <python> | | <python> |
− | >>> 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>
| |
− | >>> z.r, z.i
| |
− | (3, 4)
| |
− | >>> w.r, w.i
| |
− | (3, -4)
| |
| </python> | | </python> |
− |
| |
− | További tulajdonságokkal ruházzuk fel a Komplex osztály objektumait. Ehhez a speciális metódusokat használjuk:
| |
| | | |
| <python> | | <python> |
− | class Komplex:
| |
− | """Komplex számok kezelése."""
| |
− |
| |
− | def __init__(self, real, imag):
| |
− | """Komplex szám létrehozása"""
| |
− | self.r = real
| |
− | self.i = imag
| |
− |
| |
− | def konjugalt(self):
| |
− | return Komplex(self.r, -self.i)
| |
− |
| |
− | def __add__(self, z):
| |
− | """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>
| |
| | | |
− | Alkalmazása:
| |
− |
| |
− | <python>
| |
− | >>> 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> | | <python> |
− | >>> type(z1)
| |
− | <type 'instance'>
| |
− | >>> isinstance(z1, Komplex)
| |
− | True
| |
− | >>> z1.__class__
| |
− | <class __main__.Komplex at 0x21ce3f8>
| |
− | >>> z1.__module__
| |
− | '__main__'
| |
− | >>> z1.__class__.__name__
| |
− | 'Komplex'
| |
− | >>> dir(z1)
| |
− | ['__add__', '__doc__', '__init__', '__module__', '__repr__', 'i', 'konjugalt', 'r']
| |
− | >>> print z1.__doc__
| |
− | Komplex számok kezelése.
| |
− | >>> z1.konjugalt()
| |
− | 3 + -4i
| |
− | >>> z1.__add__(z2)
| |
− | 4 + 9i
| |
− | </python>
| |
− |
| |
− | Egy példa az osztályváltozó alkalmazására:
| |
− |
| |
− | <python>
| |
− | class Alkalmazott:
| |
− | """Alkalmazottak osztálya"""
| |
− | alkSzamlalo = 0
| |
− |
| |
− | def __init__(self, nev, fizetes):
| |
− | """Konstruktor az alkalmazottaknak"""
| |
− |
| |
− | 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> | | <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:
| |
− |
| |
− | <python>
| |
− | class Ellipszis:
| |
− |
| |
− | def __init__(self, kozeppont, felx, fely):
| |
− | self.kozeppont = kozeppont
| |
− | self.felx = felx
| |
− | self.fely = fely
| |
− |
| |
− | def terulete(self):
| |
− | return self.felx*self.fely*3.14159
| |
− | </python>
| |
− |
| |
− | Gyerek osztály:
| |
− |
| |
− | <python>
| |
− | class Kor(Ellipszis):
| |
− |
| |
− | 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>
| |
− | class Square(object):
| |
− |
| |
− | def __init__(self, side):
| |
− | self.side = side
| |
− |
| |
− | def area(self):
| |
− | """Calculates the 'area' property."""
| |
− | return self.side ** 2
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | # Google példa: http://google-styleguide.googlecode.com/svn/trunk/pyguide.html#Python_Language_Rules
| |
− |
| |
− | import math
| |
− |
| |
− | class Square(object):
| |
− | """A square with two properties: a writable area and a read-only perimeter.
| |
− |
| |
− | To use:
| |
− | >>> sq = Square(3)
| |
− | >>> sq.area
| |
− | 9
| |
− | >>> sq.perimeter
| |
− | 12
| |
− | >>> sq.area = 16
| |
− | >>> sq.side
| |
− | 4
| |
− | >>> sq.perimeter
| |
− | 16
| |
− | """
| |
− |
| |
− | def __init__(self, side):
| |
− | self.side = side
| |
− |
| |
− | def __get_area(self):
| |
− | """Calculates the 'area' property."""
| |
− | return self.side ** 2
| |
− |
| |
− | def ___get_area(self):
| |
− | """Indirect accessor for 'area' property."""
| |
− | return self.__get_area()
| |
− |
| |
− | def __set_area(self, area):
| |
− | """Sets the 'area' property."""
| |
− | self.side = math.sqrt(area)
| |
− |
| |
− | def ___set_area(self, area):
| |
− | """Indirect setter for 'area' property."""
| |
− | self.__set_area(area)
| |
− |
| |
− | area = property(___get_area, ___set_area,
| |
− | doc="""Gets or sets the area of the square.""")
| |
− |
| |
− | @property
| |
− | def perimeter(self):
| |
− | return self.side * 4
| |
− | </python>
| |
− |
| |
− | Konvenció:
| |
− |
| |
− | * _single_leading_underscore: belső használatra (Pl. <code>from M import *</code> nem tölti be ezeket)
| |
− | * single_trailing_underscore_: kerüljük a konfliktust a kulcsszavakkal (class_)
| |
− | * __double_leading_underscore: "name mangling" (a class FooBar osztálybeli __boo kint majd _FooBar__boo -ként érhető el).
| |
− | * __double_leading_and_trailing_underscore__: "különleges" objektumok (pl. __init__), saját magunk ilyeneket ne vezessünk be.
| |
− |
| |
− |
| |
− | == Funkcionális programozás elemei ==
| |
− |
| |
− | === Iterátor (bejáró) ===
| |
− |
| |
− | <python>
| |
− | >>> L = [1,2,3]
| |
− | >>> it = iter(L)
| |
− | >>> print it
| |
− | <...iterator object at ...>
| |
− | >>> it.next()
| |
− | 1
| |
− | >>> it.next()
| |
− | 2
| |
− | >>> it.next()
| |
− | 3
| |
− | >>> it.next()
| |
− | Traceback (most recent call last):
| |
− | File "<stdin>", line 1, in ?
| |
− | StopIteration
| |
− | >>>
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | for i in iter(obj):
| |
− | print i
| |
− |
| |
− | for i in obj:
| |
− | print i
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | >>> L = [1,2,3]
| |
− | >>> iterator = iter(L)
| |
− | >>> t = tuple(iterator)
| |
− | >>> t
| |
− | (1, 2, 3)
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | >>> L = [1,2,3]
| |
− | >>> iterator = iter(L)
| |
− | >>> a,b,c = iterator
| |
− | >>> a,b,c
| |
− | (1, 2, 3)
| |
− | </python>
| |
− |
| |
− | ==== Generátorkifejezés ====
| |
− |
| |
− | Hasonló a listaértelmezéshez.
| |
− |
| |
− | <python>
| |
− | (expression for expr in sequence1
| |
− | if condition1
| |
− | for expr2 in sequence2
| |
− | if condition2
| |
− | for expr3 in sequence3
| |
− | if condition3 ...
| |
− | for exprN in sequenceN
| |
− | if conditionN )
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | obj_total = sum(obj.count for obj in list_all_objects())
| |
− | </python>
| |
− |
| |
− | A generátor egy iterátort ad vissza mely adatok folyamát adja vissza.
| |
− |
| |
− | <python>
| |
− | def generate_ints(N):
| |
− | for i in range(N):
| |
− | yield i
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | >>> gen = generate_ints(3)
| |
− | >>> gen
| |
− | <generator object generate_ints at ...>
| |
− | >>> gen.next()
| |
− | 0
| |
− | >>> gen.next()
| |
− | 1
| |
− | >>> gen.next()
| |
− | 2
| |
− | >>> gen.next()
| |
− | Traceback (most recent call last):
| |
− | File "stdin", line 1, in ?
| |
− | File "stdin", line 2, in generate_ints
| |
− | StopIteration
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | def counter (maximum):
| |
− | i = 0
| |
− | while i < maximum:
| |
− | print "előtte", i
| |
− | val = (yield i)
| |
− | print "utána", i
| |
− | # If value provided, change counter
| |
− | if val is not None:
| |
− | i = val
| |
− | else:
| |
− | i += 1
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | >>> x = counter(8)
| |
− | >>> x
| |
− | <generator object counter at 0x12f50f0>
| |
− | >>> x.next()
| |
− | előtte 0
| |
− | 0
| |
− | >>> x.next()
| |
− | utána 0
| |
− | előtte 1
| |
− | 1
| |
− | >>> x.next()
| |
− | utána 1
| |
− | előtte 2
| |
− | 2
| |
− | >>> x.send(6)
| |
− | utána 2
| |
− | előtte 6
| |
− | 6
| |
− | >>> x.next()
| |
− | utána 6
| |
− | előtte 7
| |
− | 7
| |
− | >>> x.next()
| |
− | utána 7
| |
− | Traceback (most recent call last):
| |
− | File "<stdin>", line 1, in <module>
| |
− | StopIteration
| |
− | >>> x.next()
| |
− | Traceback (most recent call last):
| |
− | File "<stdin>", line 1, in <module>
| |
− | StopIteration
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | >>> def upper(s):
| |
− | ... return s.upper()
| |
− | >>>
| |
− | >>> map(upper, ['sentence', 'fragment'])
| |
− | ['SENTENCE', 'FRAGMENT']
| |
− | >>>
| |
− | >>> [upper(s) for s in ['sentence', 'fragment']]
| |
− | ['SENTENCE', 'FRAGMENT']
| |
− | </python>
| |
− |
| |
− | <python>
| |
− | >>> def is_even(x):
| |
− | ... return (x % 2) == 0
| |
− | >>>
| |
− | >>> filter(is_even, range(10))
| |
− | [0, 2, 4, 6, 8]
| |
− | >>>
| |
− | >>> [x for x in range(10) if is_even(x)]
| |
− | [0, 2, 4, 6, 8]
| |
| </python> | | </python> |
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:
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ő):