A Python egy objektumorientált programozási nyelv, amelynek alapját az objektumok képezik. (lásd C# fejezetnél) Az objektumorientált programozás (OOP) egy paradigma, amely az adatokat és a hozzájuk kapcsolódó műveleteket egységes egységekként kezeli, az úgynevezett osztályok és objektumok segítségével.
Az osztályok definíciói az adatok és a hozzájuk kapcsolódó műveletek leírását tartalmazzák. Az osztályokból objektumokat lehet létrehozni, ezek az osztályok példányai. Az objektumok állapotát, vagyis az adatokat, az objektumokra vonatkozó műveleteket, vagyis a metódusokat, valamint az objektumokkal való kapcsolattartási mechanizmust az osztályok definiálják.
Az objektumorientált programozás előnye, hogy lehetővé teszi az adatok és a hozzájuk kapcsolódó műveletek egységes kezelését, ami a fejlesztést és a karbantartást is egyszerűbbé teszi.
Az osztály olyan, mint egy tervrajz, egy példány = konkrét objektum, ami a tervrajz alapján elkészült.
Készítsük el első osztályunkat. Az osztály neve: Szemely.
Az objektumainak (emberek) 2 tulajdonságuk lesz: név, kor.
Új példányt úgy lehet létrhozni, hogy adunk neki egy nevet, megadjuk azt, melyik osztályból ‘származik’, és adunk neki konkrét adatokat. Ekkor fut le az __init__() függvény, ami létrehozza az új objektumot.
A self Pythonban az aktuális objektumra (példányra) mutató hivatkozás.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# osztály létrehozása: class Szemely: def __init__(self, nev, kor): self.neve = nev self.kora = kor # példány létrehozása: ember1 = Szemely("Teszt ELek", 42) ember2 = Szemely("Winch Eszter", 22) # első 'példány' tulajdonságainak kiíratása: print(ember1.neve) print(ember1.kora) |
Másik lehetőség, hogy írunk az osztálynak egy függvényt, aminek a visszatérési értéke az adott objektum neve és kora.
|
1 2 3 4 5 6 7 8 9 10 |
class Szemely: def __init__(self, nev, kor): self.neve = nev self.kora = kor def __str__(self): return f"{self.neve}({self.kora})" ember1 = Szemely("Teszt ELek", 42) print(ember1) |
Metódusok
Az osztályokban definiált függvényeket metódusoknak nevezzük. Többféle típusuk létezik, attól függően, hogy mit érnek el és hogyan használjuk őket.
Példánymetódus (instance method): Ez a leggyakoribb metódustípus. Az adott példány (objektum) adataival dolgozik. Első paramétere mindig self, az objektum attribútumait használja. A példában a bemutatkozas() metódus a konkrét objektumhoz tartozik.
|
1 2 3 4 5 6 7 8 9 10 |
class Szemely: def __init__(self, nev, kor): self.neve = nev self.kora = kor def bemutatkozas(self): print("Üdv! Én vagyok " + self.neve) ember1 = Szemely("Megfigy ELek", 30) ember1.bemutatkozas() |
Osztálymetódus (classmethod): az osztályra vonatkozik, nem egy konkrét példányra. @classmethod dekorátor első paramétere cls az osztály) gyakran alternatív konstruktornak használjuk. A Python közösségben a bevett konvenció: példánymetódusoknál: self osztálymetódusoknál: cls, de technikailag bármilyen nevet adhatunk nekik. A @classmethod miatt a Python automatikusan az osztályt adja át első paraméterként. Nem kell példányt létrehozni előtte
|
1 2 3 4 5 6 7 8 9 10 |
class Diak: def __init__(self, nev): self.nev = nev @classmethod def alapertelmezett(cls): return cls("Ismeretlen") d2 = Diak.alapertelmezett() print(d2.nev) |
Statikus metódus (staticmethod): nem használ sem példányt, sem osztályt. @staticmethod dekorátor, nincs self vagy cls, általános segédfüggvény
|
1 2 3 4 5 6 |
class Szamitas: @staticmethod def osszead(a, b): return a + b print(Szamitas.osszead(3, 5)) |
Nézzük meg a következő példában, hogyan lehet egyszerre mindet használni!
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
class Pelda: osztaly_valtozo = 10 def __init__(self, ertek): self.ertek = ertek # példánymetódus def duplaz(self): return self.ertek * 2 # osztálymetódus @classmethod def info(cls): return f"Osztály változó: {cls.osztaly_valtozo}" # statikus metódus @staticmethod def osszead(a, b): return a + b p = Pelda(5) print(p.duplaz()) #Példánymetódus print(Pelda.info()) #Osztálymetódus print(p.info()) # Objektumon keresztül is működik print(Pelda.osszead(3, 4)) #Statikus metódus print(p.osszead(3, 4)) # Objektumon keresztül is hívható |
Objektum tulajdonságának módosítása, törlése.
Tegyük fel, hogy szeretném átnevezni, vagy a korát átírni az első embernek. Bővítsd ki az előző programot, és máris át lett nevezve Teszt Elek
|
1 2 3 |
ember1.neve = "Senki" ember1.kora = "100" ember1.eljaras() |
Objektum tulajdonságának törlése, vagy objektum törlése: del utasítással lehetséges. (pl: del ember.neve vagy del ember1 Ha töröltük bármelyiket, akkor kiíratásnál hibaüzenetet fogunk kapni, miszerint nem létezik a tulajdonság, illetve az adott objektum nincs definiálva.
Öröklődés
Az öröklődés (inheritance) azt jelenti, hogy egy osztály átveszi egy másik osztály tulajdonságait és metódusait.
Olyan, mintha egy „szülő” osztály képességeit a „gyerek” osztály megörökölné.
Miért jó az öröklődés?
- Nem kell ugyanazt a kódot többször megírni
- Átláthatóbb program
- Újrafelhasználható kód
Nézzünk egy példát:
– minden diák is ember
– minden tanár is ember
Tehát: az Ember közös tulajdonságokat tartalmaz, a Diák és Tanár ezt örökli. Készítünk egy Diak osztályt. A Diak osztály megörökölte a koszon() metódust! A Diak osztálynak van egy saját metódusa is, tanul néven.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Ember: def __init__(self, nev): self.nev = nev def koszon(self): print(f"Szia, {self.nev} vagyok!") class Diak(Ember): def tanul(self): print("Tanulok...") d = Diak("Anna") d.koszon() d.tanul() |
Metódus felülírás (override)
A gyerek osztály át is írhatja a szülő metódusát. Írjuk át a koszon metódust!
|
1 2 3 |
class Diak(Ember): def koszon(self): print(f"Szia, diák vagyok: {self.nev}") |
Adatelrejtés (encapsulation)
Az adatelrejtés azt jelenti, hogy az objektum adatait nem engedjük közvetlenül módosítani, hanem „védjük” őket. Olyan, mintha egy „dobozba” zárnánk az adatokat. Megakadályozza a hibás használatot, biztonságosabb lesz a programunk, jobban ellenőrizhetők az adatok.
|
1 2 3 4 5 6 7 8 9 10 |
class Bankszamla: def __init__(self, egyenleg): self.__egyenleg = egyenleg def get_egyenleg(self): return self.__egyenleg def befizet(self, osszeg): if osszeg > 0: self.__egyenleg += osszeg |
Tulajdonságok (property)
A property lehetővé teszi, hogy egy változót úgy használj, mintha sima adat lenne, de közben mégis ellenőrzöd.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class Ember: def __init__(self, kor): self._kor = kor @property def kor(self): return self._kor @kor.setter def kor(self, uj_kor): if uj_kor >= 0: self._kor = uj_kor else: print("Hibás életkor!") e = Ember(20) e.kor = 25 # setter fut le print(e.kor) # getter fut le |
Feladatok, példák
Hozzunk létre egy téglalap osztályt, amely a téglalap a és b oldalának nagyságát tárolja. Adjunk az osztálynak 2 függvényt: kerület és terület kiszámítása. Adjunk egy eljárást is, ami kiírja mindegyik téglalap adatait! Ezután kérjük be 3db téglalap oldalait a felhasználótól, és mentsük el egy listába a téglalap objektumokat! Az info() eljárás meghívja a terület és kerület függvényeket minden egyes példányra.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class Teglalap: def __init__(self, a, b): self.a = a self.b = b def terulet(self): return self.a * self.b def kerulet(self): return 2 * (self.a + self.b) def info(self): print("A téglalap a oldala:", self.a) print("A téglalap b oldala:", self.b) print("A téglalap területe:", self.terulet()) print("A téglalap kerülete:", self.kerulet()) teglalapok = [] for i in range(3): a = int(input("Adja meg a(z) {} téglalap a oldalát: ".format(i+1))) b = int(input("Adja meg a(z) {} téglalap b oldalát: ".format(i+1))) teglalapok.append(Teglalap(a, b)) s=0 for teglalap in teglalapok: s=s+1 print("A(z) {} téglalap adatai".format(s)) teglalap.info() |
Informatika ágazati alapvizsga feladat: híres utazók.
Az elkészítendő program bekéri három utazó adatait (név, születési év, elhalálozás éve,
földrész). A megadott adatokat egy-egy objektumban tárolja. Az adatok megadását követően
a program írja állományba a leghosszabb ideig élt utazó nevét és földrészét!
Írjon programot utazok.py néven!
a) Az adatok tárolására használt objektumok alapját képező osztályt az utazo_alap.py fájl
tartalmazza részben elkészítve. (nincs benne a földrész, ezt kell pótolni)
b) Kérje be a felhasználótól az utazók teljes nevét, születésük és haláluk évét, valamint a
földrészt, ahol kutatásaikat végezték, és tárolja el ezeket az adatokat! A tároláshoz
egészítse ki a kapott osztályt!
c) Határozza meg, melyik utazó hány évig élt, és írja ki ezt az adatot a képernyőre pl. „Jelky
András 45 évet élt”!
d) A leghosszabb életű utazó nevét és földrészét írja a „felfedez.txt” elnevezésű fájl első
sorába!
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# ---- utazo_alap.py tartalma ---- class Utazo: def __init__(self, név, született, halál, földrész): self.név = név self.született = született self.meghalt= halál self.földrész = földrész def életkor(self): return self.meghalt - self.született # ---- main.py tartalma ---- # importáljuk az osztályt az utazo_alap.py-ből from utazo_alap import Utazo max_eletkor = -1 max_eletkor_index = -1 lista = [] for i in range(3): név = input("Kérem egy híres utazó nevét!") született = int(input("Add meg mikor született:")) meghalt = int(input("Add meg mikor halt meg:")) földrész = input("Add meg melyik földrészen tett felfedezést") #létrehozza az objektumot, tehát egy konkrét utazót ember = Utazo(név, született, meghalt, földrész) #beletesszük a listába az objektumot lista.append(ember) #adott utazó életkora, az eletkor() függvénnyel kiszámítva eletkor = ember.eletkor() #maximum kiválasztás - ha az aktuális ember életkora nagyobb, mint max, ez lesz a max if eletkor > max_eletkor: max_eletkor = eletkor max_eletkor_index = len(lista)-1 # Kiíratás - melyik utazó meddig élt for utazo in lista: eletkor = utazo.eletkor() neve = utazo.név print(f"{neve} {eletkor} évig élt") # Leghosszabb ideig élt utazó adatait kiírjuk txt-be leghosszabb_eletu = lista[max_eletkor_index] with open("felfedez.txt","w") as fajl: fajl.write(f"{leghosszabb_eletu.név} {leghosszabb_eletu.földrész}") |
