Osztályok a Pythonban
Mi az az osztály (class)?
Az osztály a Python objektumorientált programozásának alapvető építőeleme. Egy osztály olyan mint egy tervrajz vagy sablon, amely alapján objektumokat hozhatunk létre.
Újrafelhasználható
Egy osztályból több példányt is létrehozhatunk
Adatbezárás
Az adatok és a rajtuk végzett műveletek egy egységbe zárva
Öröklődés
Új osztályokat építhetünk meglévőkből
Első osztályunk: Autó
Nézzük meg egy egyszerű osztály létrehozását Python kódban:
class Auto:
"""Ez egy egyszerű autó osztály."""
def __init__(self, marka, szin):
self.marka = marka # Az autó márkája
self.szin = szin # Az autó színe
def bemutatkozas(self):
print(f"Ez egy {self.szin} színű {self.marka}.")
# Példányosítás és használat
my_car = Auto("Toyota", "piros")
my_car.bemutatkozas() # Kiírja: Ez egy piros színű Toyota.
Próbáld ki!
Osztályok vs. Szótárak
Nézzük meg, mi a különbség egy osztály és egy szótár között:
Osztály
class Szemely:
def __init__(self, nev, kor):
self.nev = nev
self.kor = kor
def koszon(self):
return f"Szia, {self.nev} vagyok!"
ember = Szemely("Anna", 25)
print(ember.koszon())
Szótár
szemely = {
"nev": "Anna",
"kor": 25
}
# Nincs beépített metódus
print(f"Szia, {szemely['nev']} vagyok!")
Hasonlítsd össze!
Osztályok Alapjai
Osztály létrehozása
Az osztályokat a class
kulcsszóval hozzuk létre. Az osztály egy tervrajz, ami alapján objektumokat (példányokat) készíthetünk.
# Egyszerű osztály létrehozása
class Kutya:
# Osztályváltozó - minden példány között megosztva
faj = "kutya"
# Konstruktor metódus
def __init__(self, nev):
# Példányváltozó - minden példánynak saját
self.nev = nev
# Objektum (példány) létrehozása
bodri = Kutya("Bodri")
print(bodri.nev) # Kiírja: Bodri
print(bodri.faj) # Kiírja: kutya
Hozz létre egy kutyát!
Osztály vs. Példány
Az osztály és a példány közötti különbség megértése alapvető fontosságú:
Osztály (Class)
- Tervrajz vagy sablon
- Meghatározza a szerkezetet
- Osztályváltozókat tartalmaz
- Metódusokat definiál
Példány (Instance)
- Konkrét objektum
- Saját adatokat tárol
- Példányváltozókat tartalmaz
- Használja az osztály metódusait
class Macska:
# Osztályváltozó
faj = "macska"
def __init__(self, nev, kor):
# Példányváltozók
self.nev = nev
self.kor = kor
# Két különböző példány
cirmi = Macska("Cirmi", 3)
mirci = Macska("Mirci", 2)
# Mindkettő ugyanazt az osztályváltozót használja
print(cirmi.faj) # macska
print(mirci.faj) # macska
# De különböző példányváltozóik vannak
print(cirmi.nev) # Cirmi
print(mirci.nev) # Mirci
Hozz létre két macskát!
Osztályok és memória
Nézzük meg, hogyan tárolódnak az objektumok a memóriában:
Konstruktor és Osztályváltozók
A konstruktor (__init__)
A konstruktor egy speciális metódus (függvény) az osztályban, ami akkor fut le automatikusan, amikor létrehozunk egy új objektumot. Ez olyan, mint egy "előkészítő" függvény: beállítja az objektum kezdeti állapotát, létrehozza és feltölti a szükséges változókat.
Pythonban ezt a __init__
metódus valósítja meg. A self
paraméter mindig az aktuális objektumra mutat, amin keresztül el tudjuk érni az objektum saját változóit.
class Jatekos:
def __init__(self, nev, eletero=100):
# Példányváltozók inicializálása
self.nev = nev
self.eletero = eletero
self.aktiv = True
def serules(self, mennyiseg):
self.eletero -= mennyiseg
if self.eletero <= 0:
self.aktiv = False
print(f"{self.nev} játékos kiesett!")
# Játékos létrehozása
player1 = Jatekos("Harcos", 120)
player2 = Jatekos("Íjász") # Alapértelmezett életerővel
Hozz létre egy játékost!
Osztályváltozók vs. Példányváltozók
Kétféle változót használhatunk az osztályokban:
- Osztályváltozók: Ezek olyan változók, amik az osztályhoz tartoznak, nem pedig az egyes objektumokhoz. Minden objektum ugyanazt az értéket látja és használja. Például egy játékban a maximális pontszám vagy egy webshopban az áfa mértéke lehet osztályváltozó.
- Példányváltozók: Ezek az egyes objektumok saját változói. Minden objektumnak saját, független példánya van belőlük. Például egy játékosnak a saját pontszáma vagy egy terméknek a saját ára.
class Szamolo:
# Osztályváltozó - minden példány között megosztva
osszes_szamolas = 0
def __init__(self, kezdoertek=0):
# Példányváltozó - minden példánynak saját
self.ertek = kezdoertek
def novel(self, mennyiseg):
self.ertek += mennyiseg
# Osztályváltozó módosítása
Szamolo.osszes_szamolas += 1
# Példányok létrehozása
szam1 = Szamolo(10)
szam2 = Szamolo(20)
szam1.novel(5) # ertek: 15, osszes_szamolas: 1
szam2.novel(10) # ertek: 30, osszes_szamolas: 2
Számlálók kezelése
Első számláló
Második számláló
Összes művelet:
Osztálymetódusok és Statikus metódusok
A normál metódusok (mint amiket eddig láttunk) mindig egy konkrét objektumon működnek, de van két speciális típusú metódus is:
- Osztálymetódusok (@classmethod): Ezek olyan függvények, amiket úgy jelölünk meg a
@classmethod
dekorátorral, hogy közvetlenül az osztályon is meghívhatók legyenek (nem kell előtte objektumot létrehozni). Az első paraméterük (cls
) az osztályt jelenti, így hozzáférnek az osztályváltozókhoz. - Statikus metódusok (@staticmethod): Ezek olyan függvények az osztályon belül, amik nem függnek sem az osztálytól, sem az objektumoktól. Olyan segédfüggvények, amik logikailag az osztályhoz tartoznak, de nem használnak osztály- vagy példányváltozókat.
A dekorátorok (mint a @classmethod
és @staticmethod
) olyan speciális jelölések Pythonban, amik módosítják a függvények viselkedését. Úgy képzeld el őket, mint egy "címkét" vagy "matricát", ami megmondja Pythonnak, hogy az adott függvényt hogyan kell kezelnie.
class Matematika:
PI = 3.14159
@classmethod
def kor_terulet(cls, sugar):
"""Osztálymetódus - használhatja az osztály adatait"""
return cls.PI * sugar * sugar
@staticmethod
def negyzet_terulet(oldal):
"""Statikus metódus - független az osztálytól"""
return oldal * oldal
# Használat példányosítás nélkül
print(Matematika.kor_terulet(5)) # Használja a PI osztályváltozót
print(Matematika.negyzet_terulet(4)) # Nem használ osztályváltozót
Geometriai számítások
Metódusok és Tulajdonságok
Metódusok az osztályokban
A metódusok olyan függvények, amelyeket az osztályon belül definiálunk. Ezek határozzák meg, hogy mit tud csinálni az objektumunk. Minden metódus első paramétere a self
, ami az aktuális objektumra mutat.
A metódusok segítségével tudjuk:
- Az objektum adatait módosítani
- Számításokat végezni az objektum adataival
- Az objektum viselkedését szabályozni
- Az objektum állapotát lekérdezni
class BankSzamla:
def __init__(self, tulajdonos, egyenleg=0):
self.tulajdonos = tulajdonos
self.egyenleg = egyenleg
def befizet(self, osszeg):
"""Pénz befizetése a számlára"""
if osszeg > 0:
self.egyenleg += osszeg
return True
return False
def kivesz(self, osszeg):
"""Pénz kivétele a számláról"""
if osszeg > 0 and osszeg <= self.egyenleg:
self.egyenleg -= osszeg
return True
return False
def egyenleg_lekerdezes(self):
"""Aktuális egyenleg lekérdezése"""
return f"{self.egyenleg} Ft"
def atutal(self, masik_szamla, osszeg):
"""Pénz átutalása másik számlára"""
if self.kivesz(osszeg):
masik_szamla.befizet(osszeg)
return True
return False
Bankszámla kezelése
1. Számla
2. Számla
Átutalás
Tulajdonságok (Properties)
A tulajdonságok lehetővé teszik, hogy az osztály adataihoz biztonságosan férhessünk hozzá. Segítségükkel:
- Ellenőrizhetjük és validálhatjuk az értékeket beállításkor
- Számított értékeket adhatunk vissza lekérdezéskor
- Elrejthetjük az osztály belső működését
- Változóként használhatjuk a metódusokat
class Teglalap:
def __init__(self, hossz, szelesseg):
self._hossz = hossz # védett változó
self._szelesseg = szelesseg
@property
def terulet(self):
"""Terület lekérdezése számított értékként"""
return self._hossz * self._szelesseg
@property
def hossz(self):
"""Hossz lekérdezése"""
return self._hossz
@hossz.setter
def hossz(self, ertek):
"""Hossz beállítása ellenőrzéssel"""
if ertek > 0:
self._hossz = ertek
else:
raise ValueError("A hossz nem lehet negatív!")
@property
def szelesseg(self):
"""Szélesség lekérdezése"""
return self._szelesseg
@szelesseg.setter
def szelesseg(self, ertek):
"""Szélesség beállítása ellenőrzéssel"""
if ertek > 0:
self._szelesseg = ertek
else:
raise ValueError("A szélesség nem lehet negatív!")
Téglalap tulajdonságainak kezelése
Öröklődés (Inheritance)
Mi az az öröklődés?
Az öröklődés az objektumorientált programozás egyik alapvető koncepciója. Lehetővé teszi, hogy egy új osztályt hozzunk létre egy meglévő osztály alapján, megörökölve annak tulajdonságait és metódusait.
Képzeld el úgy, mint egy családfát: ahogy a gyerekek öröklik szüleik tulajdonságait, úgy örökli az új osztály (gyerekosztály) a szülőosztály jellemzőit.
Kód újrafelhasználás
Nem kell ugyanazt a kódot többször megírni
Hierarchikus struktúra
Logikus kapcsolat az osztályok között
Bővíthetőség
Könnyű új funkciókat hozzáadni
class Allat:
"""Alap (szülő) osztály"""
def __init__(self, nev, kor):
self.nev = nev
self.kor = kor
def hang_ad(self):
return "Valamilyen hangot ad..."
def bemutatkozik(self):
return f"{self.nev} vagyok, {self.kor} éves."
class Kutya(Allat):
"""Származtatott (gyerek) osztály"""
def __init__(self, nev, kor, fajta):
# Szülőosztály konstruktorának hívása
super().__init__(nev, kor)
# Saját új tulajdonság
self.fajta = fajta
def hang_ad(self):
# Szülőosztály metódusának felülírása
return "Vau-vau!"
def porazzal_setalni(self):
# Saját új metódus
return f"{self.nev} pórázzal sétál."
class Madar(Allat):
"""Másik származtatott osztály"""
def __init__(self, nev, kor, szarny_meret):
super().__init__(nev, kor)
self.szarny_meret = szarny_meret
def hang_ad(self):
return "Csip-csirip!"
def repul(self):
return f"{self.nev} repül {self.szarny_meret}cm-es szárnyaival."
Állatok létrehozása
Új kutya
Új madár
Többszörös öröklődés
Pythonban egy osztály több szülőosztályból is örökölhet. Ez azt jelenti, hogy egy osztály több különböző osztály tulajdonságait és metódusait is megörökölheti.
Vigyázat! A többszörös öröklődés bonyolulttá teheti a kódot, ezért csak akkor használjuk, ha valóban szükséges!
class Repulo:
"""Első szülőosztály"""
def __init__(self):
self.repul = True
def felszall(self):
return "Felszállás..."
def leszall(self):
return "Leszállás..."
class Robot:
"""Második szülőosztály"""
def __init__(self):
self.elektromos = True
def toltottseg(self):
return "100%"
def tolt(self):
return "Töltés..."
class DronRobot(Repulo, Robot):
"""Osztály többszörös örökléssel"""
def __init__(self, nev):
# Mindkét szülő inicializálása
Repulo.__init__(self)
Robot.__init__(self)
self.nev = nev
def bemutatkozik(self):
return f"Én {self.nev} vagyok, egy repülő robot!"
Drón robot létrehozása
Speciális Metódusok
Mik azok a speciális metódusok?
A speciális metódusok (más néven "magic methods" vagy "dunder methods") olyan előre definiált nevű metódusok a Pythonban, amelyek dupla aláhúzással kezdődnek és végződnek (pl. __init__).
Ezek lehetővé teszik, hogy testreszabjuk az osztályok viselkedését különböző Python műveletekhez és beépített függvényekhez.
A leggyakrabban használt speciális metódusok:
__init__(self, ...)
- Objektum létrehozásakor fut le__str__(self)
- Az objektum szöveges megjelenítése (str() függvény)__repr__(self)
- Az objektum részletes reprezentációja (programozói nézet)__len__(self)
- A len() függvény eredménye az objektumon__add__(self, other)
- A + operátor viselkedése__eq__(self, other)
- Az == operátor viselkedése
class Pontszam:
def __init__(self, pont):
self.pont = pont
def __str__(self):
"""Felhasználóbarát szöveges megjelenítés"""
return f"{self.pont} pont"
def __repr__(self):
"""Programozói részletes megjelenítés"""
return f"Pontszam(pont={self.pont})"
def __add__(self, other):
"""+ operátor: két pontszám összege"""
if isinstance(other, Pontszam):
return Pontszam(self.pont + other.pont)
return Pontszam(self.pont + other)
def __eq__(self, other):
"""== operátor: pontszámok összehasonlítása"""
if isinstance(other, Pontszam):
return self.pont == other.pont
return self.pont == other
# Használat
p1 = Pontszam(10)
p2 = Pontszam(20)
print(p1) # 10 pont
print(repr(p1)) # Pontszam(pont=10)
print(p1 + p2) # 30 pont
print(p1 == 10) # True
Pontszámok kezelése
További gyakori speciális metódusok
Nézzünk egy példát egy olyan osztályra, amely több speciális metódust is használ:
class Kosar:
def __init__(self):
self.termekek = []
def __len__(self):
"""Termékek száma a kosárban"""
return len(self.termekek)
def __getitem__(self, index):
"""[] operátor: termék lekérése index alapján"""
return self.termekek[index]
def __iter__(self):
"""Kosár bejárhatóvá tétele (for ciklushoz)"""
return iter(self.termekek)
def __contains__(self, item):
"""in operátor: termék keresése a kosárban"""
return item in self.termekek
def add(self, termek):
self.termekek.append(termek)
# Használat
kosar = Kosar()
kosar.add("alma")
kosar.add("körte")
print(len(kosar)) # 2
print(kosar[0]) # "alma"
print("alma" in kosar) # True
for termek in kosar:
print(termek)
Bevásárlókosár kezelése
Gyakorló Feladatok
1. Feladat: Könyv osztály
Írj egy Könyv osztályt, amely kezeli egy könyv adatait (cím, szerző, oldalszám). A könyv objektumoknak legyen szöveges megjelenítése és legyenek összehasonlíthatók oldalszám alapján.
class Konyv:
def __init__(self, cim, szerzo, oldalszam):
self.cim = cim
self.szerzo = szerzo
self.oldalszam = oldalszam
def __str__(self):
return f"{self.szerzo}: {self.cim} ({self.oldalszam} oldal)"
def __eq__(self, other):
return self.oldalszam == other.oldalszam
def __lt__(self, other):
return self.oldalszam < other.oldalszam
Próbáld ki!
2. Feladat: Hőmérséklet osztály
Készíts egy Hőmérséklet osztályt, amely képes Celsius és Fahrenheit között átváltani. Használj tulajdonságokat (property) a hőmérséklet lekérdezésére és beállítására.
class Homerseklet:
def __init__(self, celsius=0):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, ertek):
self._celsius = ertek
@property
def fahrenheit(self):
return (self._celsius * 9/5) + 32
@fahrenheit.setter
def fahrenheit(self, ertek):
self._celsius = (ertek - 32) * 5/9
Hőmérséklet átváltó
3. Feladat: Bankszámla hierarchia
Hozz létre egy bankszámla osztályhierarchiát: egy alap BankSzamla osztályt, és ebből származtatott MegtakaritasiSzamla és HitelSzamla osztályokat. Mindegyik típusnak legyen saját viselkedése a pénz kivételénél.
class BankSzamla:
def __init__(self, egyenleg=0):
self.egyenleg = egyenleg
def befizet(self, osszeg):
self.egyenleg += osszeg
return True
def kivesz(self, osszeg):
if osszeg <= self.egyenleg:
self.egyenleg -= osszeg
return True
return False
class MegtakaritasiSzamla(BankSzamla):
def __init__(self, egyenleg=0, minimum_egyenleg=1000):
super().__init__(egyenleg)
self.minimum_egyenleg = minimum_egyenleg
def kivesz(self, osszeg):
if self.egyenleg - osszeg >= self.minimum_egyenleg:
return super().kivesz(osszeg)
return False
class HitelSzamla(BankSzamla):
def __init__(self, egyenleg=0, hitelkeret=100000):
super().__init__(egyenleg)
self.hitelkeret = hitelkeret
def kivesz(self, osszeg):
if self.egyenleg - osszeg >= -self.hitelkeret:
self.egyenleg -= osszeg
return True
return False