Írunk egy Person osztályt. Minden embernek lesz neve és titulusa, a __repr__
függvénnyel pedig megszólítjuk. A Knight osztály a Person leszármazottja. Minden lovag egyben ember is, de a megszólításuk egyedi. Leszármaztatni akkor tudunk, ha az ősosztályunk is az object leszármazottja. A leszármazott örökli az ősosztály összes tagváltozóját és metódusát.
class Person(object):
def __init__(self, name, title):
self.name = name
self.title = title
def __repr__(self):
return self.title + " " + self.name
class Knight(Person):
def __init__(self, name):
super(Knight, self).__init__(name, 'Sir')
varga = Person('Varga', 'Mr')
launcelot = Knight('Launcelot')
print varga
print launcelot
A leszármazott osztályban definiálhatunk új tagváltozókat is. Például legyen minden lovagnak egy opcionális epitheton ornansa!
class Person(object):
def __init__(self, name, title):
self.name = name
self.title = title
def __repr__(self):
return self.title + " " + self.name
class Knight(Person):
def __init__(self, name, eo=""):
super(Knight, self).__init__(name, 'Sir')
self.eo = eo
launcelot = Knight('Launcelot', 'the brave')
launcelot
Minden lovag megérdemli, hogy a neve mellé az állandó jezőjét is hozzáfűzzük. Ehhez felüldefiniáljuk a __repr__
metódust. Azonos nevű metódusok esetén mindig a leszármazottban definiált élvez elsőbbséget és hívódik meg.
class Person(object):
def __init__(self, name, title):
self.name = name
self.title = title
def __repr__(self):
return self.title + " " + self.name
class Knight(Person):
def __init__(self, name, eo=""):
super(Knight, self).__init__(name, 'Sir')
self.eo = eo
def __repr__(self):
if len(self.eo) > 0:
return self.title + " " + self.name + ", " + self.eo
else:
return super(Knight, self).__repr__()
launcelot = Knight('Launcelot', 'the brave')
black = Knight('Black')
robin = Knight('Robin', 'the Not-quite-so-brave-as-Sir-Launcelot')
print launcelot
print black
print robin
Van mód arra is, hogy bizonyos változókat osztályszinten definiáljunk. Ilyen például a lovagok "Sir" megszólítása.
Hogy ne essen egybe a Person title változójával, nevezzük special_title
-nek.
Ahhoz, hogy az osztályszintű változót elérjük, a Knight.special_title
-ra kell hivatkozni, de bármelyik példány .special_title
változója is erre mutat.
class Person(object):
def __init__(self, name, title):
self.name = name
self.title = title
def __repr__(self):
return self.title + " " + self.name
class Knight(Person):
special_title = 'Sir'
def __init__(self, name, eo=""):
super(Knight, self).__init__(name, "")
self.eo = eo
def __repr__(self):
return Knight.special_title + " " + self.name + ", " + self.eo
launcelot = Knight('Launcelot', 'the brave')
robin = Knight('Robin', 'the Not-quite-so-brave-as-Sir-Launcelot')
print launcelot
print robin
print robin.special_title, launcelot.special_title, Knight.special_title
Megjegyezzük, hogy az öröklési lánc tetszőlegesen hosszú lehet, illetve lehet egyszerre több osztályból örökölni.
Vannak olyan esetek, amikor a kód hibába ütközik. Ilyenkor egy Exception típusú objektumot dob (emel) a python.
Ekkor
Kivéve, ha
try:
...
except ... :
...
blokkalEgy Exceptiont bármikor el lehet kapni, akármennyi fügvényhívást túlél. Nézzünk egy példát! Most mi magunk hívjuk elő a hibát (raise), de egyben le is kezeljük.
try:
raise Exception('spam', 'eggs')
except Exception as inst:
print type(inst)
print inst.args
print inst
x, y = inst.args
print 'x =', x
print 'y =', y
Most pedig lekezelünk egy nem mesterségesen létrehozott kivételt.
try:
str(5) + 5
except TypeError as inst:
print type(inst)
print inst.args
print inst
Természetes környezetben. Ha a felhasználó nem egész számot ad, nem tudja azzá konvertálni, így hibát jelez, mi viszont ezt lekezeljük.
while True:
try:
x = int(raw_input("Please enter a number: "))
break
except ValueError:
print "Oops! That was no valid number. Try again..."
print 2*x
Nézzük meg hogy hol történt a kivétel dobása (raise) és és hol az elkapása.
def f(x):
return x + 5 # nem jó ha x egy string
def g(x):
return x + x # ez jó int-re és str-re is
x = "5"
y = g(x)
z = f(y)
Írhatunk saját kivétel osztályt is, ezt arra tudjuk használni, hogy egyedi hibákat jelezzünk vele.
Csupán az Exception
beépített osztályból kell öröklődni (opcionálisan mást is lehet bele rakni).
class KnightException(Exception):
pass
lancelot = Person("Lancelot", "Mr")
x = lancelot.__repr__()
if x[:3] != "Sir":
raise KnightException("a", "b")
Láttuk, hogy a for i in L
nem csak akkor működik, ha L
lista.
Pontosan mely objektumok állhatnak a for ... in
után?
A for
meghívja az iter()
függvényt, mely egy iterálható objektumot ad vissza, melyre definiálva van egy next()
függvény, amely minden meghívására visszaadja az objektum egy elemét. Ha a next()
nem talál több elemet, egy StopIteration
kivételt dob.
Iterálható az az objektum, aminek van next
metódusa.
for ... in
után az állhat, aminek van __iter__ metódusa, ami iterálható objektumot ad vissza.
Ezek speciális metódusok!
r = range(3)
it = iter(r)
next(it)
print next(it)
print next(it)
next(it)
Tetszőleges, általunk definiált osztályhoz is adható iterátor tulajdonság. Először is szükség van egy __iter__
függvényre, ami egy olyan objektummal tér vissza, ami iterálható. Az iterálható objekcumok (list, set, tuple
) definiálnak egy next()
metódust, ami sorban visszaadja az elemeket.
Ha kifogyott, akkor StopIteration kivételt emel.
class Person(object):
def __init__(self, name, title=""):
self.name = name
self.title = title
def __repr__(self):
return self.title + " " + self.name
class Knight(Person):
title = 'Sir'
searching_for = 'The Holy Grail'
def __init__(self, name, eo):
super(Knight, self).__init__(name)
self.eo = eo
def __repr__(self):
return Knight.title + " " + self.name + ", " + self.eo
class Group(object):
def __init__(self, name, persons):
self.persons = persons
self.name = name
def __iter__(self):
self.index = 0
return self
def next(self):
if self.index >= len(self.persons):
raise StopIteration # dobunk egy kivetelt
self.index += 1
return self.persons[self.index - 1]
kotrt = Group('Knights of The Round Table',
[Knight('Launcelot', 'the brave'),
Knight('Galahad', 'the pure'),
Knight('Bedevere', 'the wise'),
Knight('Robin', 'the Not-quite-so-brave-as-Sir-Launcelot')])
for knight in kotrt:
print knight
Vigyázzunk, hogy az indexet vissza kell állítani, különben csak egyszer tudunk iterálni! Persze mindezt megoldhattuk volna egyszerűbben.
class Person(object):
def __init__(self, name, title=""):
self.name = name
self.title = title
def __repr__(self):
return self.title + " " + self.name
class Knight(Person):
title = 'Sir'
searching_for = 'The Holy Grail'
def __init__(self, name, eo):
super(Knight, self).__init__(name)
self.eo = eo
def __repr__(self):
return Knight.title + " " + self.name + ", " + self.eo
class Group:
def __init__(self, name, persons):
self.persons = persons
self.name = name
def __iter__(self):
return iter(self.persons)
kotrt = Group('Knights of The Round Table',
[Knight('Launcelot', 'the brave'),
Knight('Galahad', 'the pure'),
Knight('Bedevere', 'the wise'),
Knight('Robin', 'the Not-quite-so-brave-as-Sir-Launcelot')])
for knight in kotrt:
print knight