Informatika2-2012/Eloadas10

A MathWikiből
(Változatok közti eltérés)
(with értelmezése)
(yield hogyan)
 
(egy szerkesztő 23 közbeeső változata nincs mutatva)
1. sor: 1. sor:
 +
[http://wiki.math.bme.hu/view/Informatika2-2012 <-- vissza]
 +
 
== Osztályok és kivételek ==
 
== Osztályok és kivételek ==
  
14. sor: 16. sor:
 
Az előbbi kód egy alap gyűjtő osztályt reprezentál.
 
Az előbbi kód egy alap gyűjtő osztályt reprezentál.
  
=== Kivételek ===
+
<python>
 +
class MyClass:
 +
  gvar = 667
 +
 
 +
  def fv(self):
 +
    pass
 +
</python>
 +
 
 +
A '''gvar''' változó a MyClass osztály szintű azaz az osztály nevével elérhető nem kell példányosítani.
 +
Az '''fv''' metódus csak példányon, vagy létező példánnyal hívható meg.
 +
 
 +
Eddig definíciókat írtunk. Olyan mint a fv definíció, ez még magában nem fut le, csak definiálunk egy típust.
 +
Az osztályokat a program futása során példányosítjuk.
 +
 
 +
<python>
 +
x = MyClass()
 +
# hasonloan mint mondjuk egy listát
 +
l = list()
 +
# vagy mas tipusokat ugyanis minden elem a python-on belül osztály lesz
 +
d = dict()
 +
</python>
 +
 
 +
Amikor egy osztályt példányosítunk akkor a példányon elérjük az osztály definíciójában definiált változókat és függvényeket.
 +
 
 +
<python>
 +
x = MyClass()
 +
x.fv()
 +
MyClass.fv(x) # a két fv. hívás megegyezik
 +
</python>
 +
 
 +
Az osztály elemeit nem szükséges a definíció során megadni. Utólag is hozzáadhatjuk.
 +
 
 +
<python>
 +
x.count = 1
 +
x.count += 1
 +
# es szinten torolheto is
 +
del(x.count)
 +
</python>
 +
 
 +
A python osztályok alapvetően nem valók absztrakt definiálásra, ebben van az egyszerűsége.
 +
 
 +
Ha a osztály definíciójában használunk változókat, akkor azokat látják a létrehozott példányok is, de csak addig míg felül nem írják...
 +
 
 +
=== öröklés ===
 +
<python>
 +
>>> class A(object):
 +
...  pass
 +
...
 +
>>> a = A()
 +
>>> a.t = 5
 +
>>> a.t
 +
5
 +
</python>
 +
 
 +
Alapvetően minden osztály az '''object''' alosztálya. Az alosztály örökli az ős minden elemét. Így már létező működést tudunk az új típus (osztály) - ra tenni. Ezzel újrahasznosítani a már létező kódot.
 +
 
 +
Pythonon belül egyszerre több osztálytól is leszármazhatunk.
 +
 
 +
<python>
 +
class A(B, C):
 +
  pass
 +
</python>
 +
 
 +
Itt az A osztály a B és a C -től is leszármazik.
 +
 
 +
Pythonon belül minden publikus változó, azaz ha én látom az osztály példányát akkor elérek belőle mindent. Ezért úgymond kitaláltak egy konvenciót, amit illik betartani:
 +
Megegyezés szerint.
 +
* '''_elem''' - fél privát (csak kritikus esetben írjuk direkt)
 +
* '''__elem''' - privát (soha ne írjuk felül)
 +
 
 +
'''isinstance''' - lehet vizsgálni változóról, hogy milyen példány.
 +
<python>
 +
>>> isinstance(object, int)
 +
False
 +
>>> isinstance(int, object)
 +
True
 +
>>> isinstance(x, object)
 +
True
 +
</python>
 +
 
 +
'''issubclass''' - a leszármazást lehet vele vizsgálni hasonló képen
 +
 
 +
Több osztályt is megadhatunk leszármazás során
 +
<python>
 +
class A(B,C):
 +
  pass
 +
</python>
 +
 
 +
=== konstruktor, operátorok ===
 +
Az '''__init__''' metódus az osztály konstruktorát reprezentálja. Amikor létrehozunk egy példányt az osztályból ez a függvény hívódik meg.
 +
 
 +
A '''__repr__''' - a repr() által visszaadott elemet definiálhatjuk, hasonló képen a '''__str__''' a str() fv-vel.
 +
 
 +
<python>
 +
class Position3D:
 +
  def __init__(self,x,y,z):
 +
    self.pos = (x,y,z)
 +
 
 +
  def get_y():
 +
    return self.pos[1]
 +
 
 +
  def __repr__(self):
 +
    return 'This position is in:\n\tx: {0:d}, y: {1:d}, z:{2:d}'.format(self.pos[0],self.pos[1],self.pos[2])
 +
</python>
 +
 
 +
További operátorok:
 +
* iterátor lekérése (iter fv.)
 +
__iter__,
 +
* +, -, /, stb. operátorok
 +
__mul__, __add__,
 +
* lista elem lekérés, slice ([], [:])
 +
__getitem__, __setitem__, __getslice__
 +
* attribútum lekérése (.)
 +
__getattr__,
 +
* hívás (())
 +
__call__,
 +
* törlése (del fv.)
 +
__del__,
 +
* hossza (len fv.)
 +
__len__,
 +
* összehasonlító operátorok (==, <, <=, >, >=, !=)
 +
__eq__, __lt__, __le__, __gt__, __ge_, __ne__
 +
* stb
 +
__cmp__,
 +
 
 +
[http://docs.python.org/library/operator.html#mapping-operators-to-functions syntax]
 +
 
 +
=== super() függvény ===
 +
a super fv egy típust vár paraméterként és visszaad egy "proxy"-t amin keresztül elérjük az ős függvényeit.
 +
A proxy-n az operátorok nem használhatók!
 +
 
 +
super(<type>) - type ősének közvetítőjét adja vissza
 +
super(<type>, <obj>) - type ősének közvetítőjét adja vissza ha az obj type típusú
 +
super(<type1>, <type2>) - az type1 type2 ősének közvetítőjét adja vissza (többes öröklés esetén)
 +
 
 +
<python>
 +
class A(object):
 +
  def __init__(self, x):
 +
    self.hey = x * x
 +
 
 +
class B(A):
 +
  def __init__(self, x, y):
 +
    self.zed = y / x
 +
    super(B, self).__init__(x)
 +
 
 +
print B
 +
a = A(5)
 +
print a.hey
 +
b = B(5, 30)
 +
print b.zed, b.hey
 +
</python>
 +
 
 +
[http://docs.python.org/library/functions.html#super super függvény leírása]
 +
 
 +
== Kivételek ==
 +
A kivétel olyan nyelvi elem, ami a keletkezésénél megszakítja a program futását, majd amíg nincs lekezelve mozog a program kezdeti blokkjáig, ahol az interpreter elnyeli és kilép a program futtatásából.
 +
 
 +
Ha a kivétel valahol le van kezelve, és a lekezelés során nem lépünk ki a programból, akkor a program a lekezelő blokk után fogja folytatni a futását.
 +
 
 +
Kivétel keletkezik ha nullával próbálunk osztani, ha a behúzás a program során nem egységes, ill. ha egy fájlt nem tudunk megnyitni olvasásra...
 +
 
 +
== kivételek kezelése ==
 +
A kivételekre lehet azért számítani, és ha kell akkor megfelelően lekezelni a következő módon:
 +
 
 
<python>
 
<python>
 
try:
 
try:
25. sor: 190. sor:
 
   ...
 
   ...
 
</python>
 
</python>
 +
 +
Kivételek elemei:
 +
<python>
 +
>>> try:
 +
...    raise Exception('spam', 'eggs')
 +
... except Exception as inst:
 +
...    print type(inst)    # the exception instance
 +
...    print inst.args      # arguments stored in .args
 +
...    print inst          # __str__ allows args to printed directly
 +
...    x, y = inst          # __getitem__ allows args to be unpacked directly
 +
...    print 'x =', x
 +
...    print 'y =', y
 +
...
 +
<type 'exceptions.Exception'>
 +
('spam', 'eggs')
 +
('spam', 'eggs')
 +
x = spam
 +
y = eggs
 +
</python>
 +
 +
A kivételek is osztályok, és azok is leszármaztathatók.
 +
<python>
 +
>>> class B():
 +
...  pass
 +
...
 +
>>> class C(B):
 +
...  pass
 +
...
 +
>>> class D(C):
 +
...  pass
 +
...
 +
>>> for c in [B,C,D]:
 +
...  try:
 +
...    raise c()
 +
...  except D:
 +
...    print "d"
 +
...  except C:
 +
...    print 'c'
 +
...  except B:
 +
...    print 'b'
 +
...
 +
b
 +
c
 +
d
 +
</python>
 +
 +
[http://docs.python.org/tutorial/errors.html egy magyarázat]
  
 
=== with értelmezése ===
 
=== with értelmezése ===
 +
A '''with''' kulcsszó alapvetően erőforrások lefoglalására majd a with blokk elhagyása után azok felszabadítására használható. Bővebb értelemben pedig bármire, amit a blokk előtt és után mindig le szeretnénk futtatni.
 +
 +
<python>
 +
with obj as var:
 +
  ...code block
 +
</python>
 +
 
Egyenértékű kód:
 
Egyenértékű kód:
 +
 
<python>
 
<python>
 
__enter__()
 
__enter__()
34. sor: 254. sor:
 
finally:
 
finally:
 
   __exit__()
 
   __exit__()
 +
 +
# azaz
 +
 +
with <valami> as <valt>:
 +
  doSth()
 
</python>
 
</python>
 +
 +
A mélyére ásva a with akkor használható, ha az objektumnak amin értelmezett (obj) definiált az '''__enter__''' és a '''__exit__''' operátor. Ugyanis ahogy látszik az egyenértékű kódon ezeket hajtja végre a blokk elején és végén. Az as után álló var pedig az __enter__ visszatérési értéke lesz, amit felhasználhatunk a blokkon belül.
  
 
[http://effbot.org/zone/python-with-statement.htm egy magyarázat]
 
[http://effbot.org/zone/python-with-statement.htm egy magyarázat]
  
=== iterátorok ===
+
== iterátorok ==
  
=== yield hogyan ===
+
iterátorok segítségével tudjuk a sorozatokat bejárni. Az '''iter''' fv képes visszaadni a sorozat iterátorát amin a '''next''' fv segítségével lehet lépegetni.
 +
 
 +
<python>
 +
>>> t='alma'
 +
>>> i=iter(t)
 +
>>> i
 +
<iterator object at 0xb73c4dec>
 +
>>> i.next()
 +
'a'
 +
>>> i.next()
 +
'l'
 +
>>> i.next()
 +
'm'
 +
>>> i.next()
 +
'a'
 +
>>> i.next()
 +
Traceback (most recent call last):
 +
  File "<stdin>", line 1, in <module>
 +
StopIteration
 +
</python>
 +
 
 +
== yield hogyan ==
 
Memória barát funkcionális program elem, generátor
 
Memória barát funkcionális program elem, generátor
  
==== generátor ====
+
=== generátor ===
  
[http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained egy magyarázat]
+
a generátor egy olyan különleges iterátor, aminek az elemei nem foglalnak helyet a memóriában, hanem lépésről lépésre "generálódik". A generátor elemein csak egyszer tudsz végig menni. [http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained egy magyarázat]
 +
 
 +
==== generátor kifejezés ====
 +
<python>
 +
(i*i for i in range(1,11))
 +
</python>
 +
 
 +
Ez a kód egy generátort eredményez, ami 1 - 10 négyzetét adja vissza elemeiként. [http://www.python.org/dev/peps/pep-0289/ bővebb leírás]
 +
 
 +
<python>
 +
def reverse(data):
 +
    for index in range(len(data)-1, -1, -1):
 +
        yield data[index]
 +
 
 +
>>> for char in reverse('golf'):
 +
...    print char
 +
...
 +
f
 +
l
 +
o
 +
g
 +
</python>

A lap jelenlegi, 2012. szeptember 4., 23:38-kori változata

<-- vissza

Tartalomjegyzék

Osztályok és kivételek

Osztályok

Az osztályokat alapvetően egységbezárásra használják. Ami által a program tagolhatósága és újrahasznosítása nő.

Osztályok változókból és metódusokból állnak.

class MyClass:
  pass

Az előbbi kód egy alap gyűjtő osztályt reprezentál.

class MyClass:
  gvar = 667
 
  def fv(self):
    pass

A gvar változó a MyClass osztály szintű azaz az osztály nevével elérhető nem kell példányosítani. Az fv metódus csak példányon, vagy létező példánnyal hívható meg.

Eddig definíciókat írtunk. Olyan mint a fv definíció, ez még magában nem fut le, csak definiálunk egy típust. Az osztályokat a program futása során példányosítjuk.

x = MyClass()
# hasonloan mint mondjuk egy listát
l = list()
# vagy mas tipusokat ugyanis minden elem a python-on belül osztály lesz
d = dict()

Amikor egy osztályt példányosítunk akkor a példányon elérjük az osztály definíciójában definiált változókat és függvényeket.

x = MyClass()
x.fv()
MyClass.fv(x) # a két fv. hívás megegyezik

Az osztály elemeit nem szükséges a definíció során megadni. Utólag is hozzáadhatjuk.

x.count = 1
x.count += 1
# es szinten torolheto is
del(x.count)

A python osztályok alapvetően nem valók absztrakt definiálásra, ebben van az egyszerűsége.

Ha a osztály definíciójában használunk változókat, akkor azokat látják a létrehozott példányok is, de csak addig míg felül nem írják...

öröklés

>>> class A(object):
...   pass
... 
>>> a = A()
>>> a.t = 5
>>> a.t
5

Alapvetően minden osztály az object alosztálya. Az alosztály örökli az ős minden elemét. Így már létező működést tudunk az új típus (osztály) - ra tenni. Ezzel újrahasznosítani a már létező kódot.

Pythonon belül egyszerre több osztálytól is leszármazhatunk.

class A(B, C):
  pass

Itt az A osztály a B és a C -től is leszármazik.

Pythonon belül minden publikus változó, azaz ha én látom az osztály példányát akkor elérek belőle mindent. Ezért úgymond kitaláltak egy konvenciót, amit illik betartani: Megegyezés szerint.

  • _elem - fél privát (csak kritikus esetben írjuk direkt)
  • __elem - privát (soha ne írjuk felül)

isinstance - lehet vizsgálni változóról, hogy milyen példány.

>>> isinstance(object, int)
False
>>> isinstance(int, object)
True
>>> isinstance(x, object)
True

issubclass - a leszármazást lehet vele vizsgálni hasonló képen

Több osztályt is megadhatunk leszármazás során

class A(B,C):
  pass

konstruktor, operátorok

Az __init__ metódus az osztály konstruktorát reprezentálja. Amikor létrehozunk egy példányt az osztályból ez a függvény hívódik meg.

A __repr__ - a repr() által visszaadott elemet definiálhatjuk, hasonló képen a __str__ a str() fv-vel.

class Position3D:
  def __init__(self,x,y,z):
    self.pos = (x,y,z)
 
  def get_y():
    return self.pos[1]
 
  def __repr__(self):
    return 'This position is in:\n\tx: {0:d}, y: {1:d}, z:{2:d}'.format(self.pos[0],self.pos[1],self.pos[2])

További operátorok:

  • iterátor lekérése (iter fv.)

__iter__,

  • +, -, /, stb. operátorok

__mul__, __add__,

  • lista elem lekérés, slice ([], [:])

__getitem__, __setitem__, __getslice__

  • attribútum lekérése (.)
__getattr__,
  • hívás (())

__call__,

  • törlése (del fv.)

__del__,

  • hossza (len fv.)

__len__,

  • összehasonlító operátorok (==, <, <=, >, >=, !=)

__eq__, __lt__, __le__, __gt__, __ge_, __ne__

  • stb

__cmp__,

syntax

super() függvény

a super fv egy típust vár paraméterként és visszaad egy "proxy"-t amin keresztül elérjük az ős függvényeit. A proxy-n az operátorok nem használhatók!

super(<type>) - type ősének közvetítőjét adja vissza super(<type>, <obj>) - type ősének közvetítőjét adja vissza ha az obj type típusú super(<type1>, <type2>) - az type1 type2 ősének közvetítőjét adja vissza (többes öröklés esetén)

class A(object):
  def __init__(self, x):
    self.hey = x * x
 
class B(A):
  def __init__(self, x, y):
    self.zed = y / x
    super(B, self).__init__(x)
 
print B
a = A(5)
print a.hey
b = B(5, 30)
print b.zed, b.hey

super függvény leírása

Kivételek

A kivétel olyan nyelvi elem, ami a keletkezésénél megszakítja a program futását, majd amíg nincs lekezelve mozog a program kezdeti blokkjáig, ahol az interpreter elnyeli és kilép a program futtatásából.

Ha a kivétel valahol le van kezelve, és a lekezelés során nem lépünk ki a programból, akkor a program a lekezelő blokk után fogja folytatni a futását.

Kivétel keletkezik ha nullával próbálunk osztani, ha a behúzás a program során nem egységes, ill. ha egy fájlt nem tudunk megnyitni olvasásra...

kivételek kezelése

A kivételekre lehet azért számítani, és ha kell akkor megfelelően lekezelni a következő módon:

try:
  ...
except <exp> as <v>:
  ...
else:
  ...
finally:
  ...

Kivételek elemei:

>>> try:
...    raise Exception('spam', 'eggs')
... except Exception as inst:
...    print type(inst)     # the exception instance
...    print inst.args      # arguments stored in .args
...    print inst           # __str__ allows args to printed directly
...    x, y = inst          # __getitem__ allows args to be unpacked directly
...    print 'x =', x
...    print 'y =', y
...
<type 'exceptions.Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

A kivételek is osztályok, és azok is leszármaztathatók.

>>> class B():
...   pass
... 
>>> class C(B):
...   pass
... 
>>> class D(C):
...   pass
... 
>>> for c in [B,C,D]:
...   try:
...     raise c()
...   except D:
...     print "d"
...   except C:
...     print 'c'
...   except B:
...     print 'b'
... 
b
c
d

egy magyarázat

with értelmezése

A with kulcsszó alapvetően erőforrások lefoglalására majd a with blokk elhagyása után azok felszabadítására használható. Bővebb értelemben pedig bármire, amit a blokk előtt és után mindig le szeretnénk futtatni.

with obj as var:
  ...code block

Egyenértékű kód:

__enter__()
try:
  doSth()
finally:
  __exit__()
 
# azaz
 
with <valami> as <valt>:
  doSth()

A mélyére ásva a with akkor használható, ha az objektumnak amin értelmezett (obj) definiált az __enter__ és a __exit__ operátor. Ugyanis ahogy látszik az egyenértékű kódon ezeket hajtja végre a blokk elején és végén. Az as után álló var pedig az __enter__ visszatérési értéke lesz, amit felhasználhatunk a blokkon belül.

egy magyarázat

iterátorok

iterátorok segítségével tudjuk a sorozatokat bejárni. Az iter fv képes visszaadni a sorozat iterátorát amin a next fv segítségével lehet lépegetni.

>>> t='alma'
>>> i=iter(t)
>>> i
<iterator object at 0xb73c4dec>
>>> i.next()
'a'
>>> i.next()
'l'
>>> i.next()
'm'
>>> i.next()
'a'
>>> i.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

yield hogyan

Memória barát funkcionális program elem, generátor

generátor

a generátor egy olyan különleges iterátor, aminek az elemei nem foglalnak helyet a memóriában, hanem lépésről lépésre "generálódik". A generátor elemein csak egyszer tudsz végig menni. egy magyarázat

generátor kifejezés

(i*i for i in range(1,11))

Ez a kód egy generátort eredményez, ami 1 - 10 négyzetét adja vissza elemeiként. bővebb leírás

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]
 
>>> for char in reverse('golf'):
...     print char
...
f
l
o
g
Személyes eszközök