Informatika2-2015/Eloadas 6 Python-6 Objektumok definialasa

A MathWikiből
A lap korábbi változatát látod, amilyen Csirke (vitalap | szerkesztései) 2015. március 18., 12:04-kor történt szerkesztése után volt.
(eltér) ←Régebbi változat | Aktuális változat (eltér) | Újabb változat→ (eltér)

Tartalomjegyzék

Objektumok definiálása

Tuple, szótár használata

A mai óra folyamán ezzel a példakóddal fogunk foglalkozni. Ez lehetne pl. egy program része amit egy hallgató írt hogy segítsen összeállítani az órarendjét:

link

(Megjegyzés: Az objektumorientált programozás, a kivételekkel való hibakezeléshez hasonlóan, olyan technológia, amelynek az előnyei igazán csak nagyobb programok írásánál jönnek elő. Ilyen kis példánál el kell túlozni a problémák nagyságát ahhoz hogy megindokoljuk ezen technikák használatát, de attól még hogy itt esetleg a megoldás bonyolultabbnak tűnik mint a probléma, nagyobb programoknál ugyanez a megoldás már jobb arányt produkál.)

Nézzük csak, mi történik, ha szeretném külön számontartani, hogy az óraszámból mennyi olyan, ahol jelenlétet ellenőriznek. Az lenne a logikus, ha a tuple-ben azössz óraszám mellett lenne. Ezért más kódot is módosítani kell, míg végül valami ilyesmire jutunk:

link

A fontos dolog az, hogy megváltoztattam hogy mit tárolok el egy-egy tárgyról, és emiatt meg kellett változtatnom az osszkredit függvényt, pedig a krediteket így is, úgy is eltároltam. Ebből látható, hogy az ilyen tuple-ös (vagy listás) megoldás nem fenntartható, ha valamit változtatni akarok a tárolási módszeren, akkor annak következtében mindenhol a kódban változtatnom kell, ahol ezeket az adatokat használom.

Egyik alternatíva szótárban tárolni a dolgokat. Ekkor a lista minden eleme egy szótár, ami pontosan ugyanazokat a kulcsokat tartalmazza:

link

Ez nem egy rossz megoldás, így már be lehet rakni új tulajdonságokat nagyobb probléma nélkül. Azért még van vele egy-két probléma:

  • Mindegyik tantárgy létrehozásánál le kell írni az adatmezők neveit (azt hogy "nev", "oraszam", stb.).
  • Ha a kódban több hely is van, ahol létrehozok ilyen tantárgyakat, akkor ha bevezetek ilyen új adatot, akkor mindenhol módosítani kéne, és lehet hogy csak később derül ki ha valahol elfelejtettük módosítani.
  • Minden függvénynél ami ilyen formátumban tárolt tantárgyakat vár, dokumentálni kell, hogy ez pontosan mit jelent.

Ezeket még kb. meg lehet oldani ha bevezetünk egy ujtargy() nevű függvényt, és mindig azt használjuk ha tantárgyat akarunk létrehozni a kódban:

link

Ez a dokumentáláson is segít, írhatja azt pl. az osszora() függvény dokumentációja hogy "A minden paraméter tantárgyak adatait tartalmazó szótárakat tartalmaz, melyek az ujtargy() függvénnyel lettek létrehozva. Azt is megoldja, hogy ha a kódban elfelejtjük mindenhol betenni a plusz paramétereket, akkor már egyből az objektum létrehozásakor szólni fog a python hogy van hiányzó paraméter, nem csak később, használat közben derül ki esetleg a hiba.

Így már elég közel járunk egy tényleges osztály koncepcióhoz, csak még a python erre kitalált szintaxisát nem használtuk. Térjünk rá arra:

Python class

Osztály definiálás

Python-ban saját osztályt a class és az object kulcsszavak használatával tudunk létrehozni. A legegyszerűbb példa így nézne ki:

class Targy(object):
    pass

(Szokás az osztályok neveit mind nagybetűsnek venni, hogy könnyebben megkülönböztethető legyen. A python dokumentáció is ajánlja ezt mint egy lehetőséget, bár a python beépített osztályok nem követik ezt a módszert.) Az "object" helyére kerülhetne más is elvileg, de hogy az mit jelent, oda ebből a tárgyból már nem jutunk el, nekünk ott mindig az lesz hogy "object".

Ezen az osztályon belül lehet aztán különböző függvényeket definiálni, ezek lesznek az osztály metódusai. Néhány függvény név speciális, ilyen az __init__(), ami az osztály konstruktora. Minden függvénynek amit az osztályon belül definiálunk, az első paramétere speciális lesz, ezt általában "self"-nek szokták elnevezni. Nézzük a korábbi példát most már osztállyal megvalósítva.

link

Láthatjuk hogy a fenti két függvényben már hozzáférhetünk a tagváltozóhoz úgy hogy targy.nev, és ilyesmi, ami valamivel szebb mint a targy["nev"], mert jelzi hogy a lehetséges nevek azok az objektum fix tagváltozói lehetnek. Amik a targy __init__-jének a paraméterei a self-en kívül, azokat kell megadni létrehozáskor, mást nem fogad el a program. (Legalábbis más darabszám paramétert. Azt elfogadja ha hülyeséget adunk meg.)

Metódusok

Más metódusokat is lehet definiálni az osztályban. Ezeknél is, amikor definiáljuk őket, az első paraméter legyen a self. A metóduson belül a self változón keresztül férhetünk hozzá az aktuális objektum tagváltozóihoz. Példa:

link

És persze módosíthatjuk is az objektum tartalmát a metódusokból:

class Targy(object):
    def __init__(self, nev, oraszam, jelenlet, kredit):
        self.nev = nev
        self.oraszam = oraszam
        self.jelenlet = jelenlet
        self.kredit = kredit
 
    def valtozott_kreditszam(self, uj_kredit):
        self.kredit = uj_kredit

Objektum-orientált paradigma

Ez a megoldás így, eddig, nem tud semmivel se többet mint a szótáras megoldás. (Későbbi dolgokra ez nem lesz teljesen igaz.) De most tegyünk egy kis kitérőt az objektum-orientált programozásról.

Az objektum-orientált programozás egy programozási paradigma, tehát egy módszer a nagy programok szervezésére. A paradigma használata független a szintaxistól. Ha, az óra elején mutatott módon, szótárakkal tárolnánk a különböző objektumok tagváltozóit, akkor is követhetjük az objektum-orientált paradigmát. Csak az kell, hogy szigorúan kövessük a szabályokat: csak az ujtargy() függvénnyel hozzunk létre tantárgy "objektumokat", legyenek "metódusaink", amik első paraméternek egy ilyen tantárgy "objektumot" (szótárat) kapnak, és azzal dolgoznak. (Ezeknek a függvényeknek a hívásakor így nekünk kell kézzel átadni a célobjektumot.)

Azonban a speciális szintaxis használata kicsit egyszerűbbé teszi a szabályok követését, és jelzi más programozóknak hogy itt objektum-orientáltan programozunk. (Vannak programozási nyelvek, pl. a C, amikben nincs ehhez megfelelő szintaxis, és ezért az előbb említett trükköket használják amikor objektum-orientált programot írnak.)

Tehát különböző programozási nyelvek különböző mértékben segítik, vagy követelik meg az objektum-orientált programozás használatát. Pl. a Java és C# nyelv megköveteli, nem enged olyan kódot írni ami nincs objektumon belül. Azt a kódot is, amit a program indításakor akarunk hogy lefusson, valamelyik osztály main() nevű metódusába kell tenni. Ennek megfelelő valahogy így nézne ki pythonban:

link

A python valahol félúton van: van szintaxis az objektum-orientált programozáshoz, bár olyan szigorúságot nehéz elérni mint más objektum-orientált nyelveken. Nem követeli meg az objektum orientált gondolkozást, így lehet akár olyan egyszerű programot is írni hogy:

link

és ez egy teljes és működő python program. Azonban a python-ban is kb. minden egy "objektum", a beépített listák, karakterláncok, szótárak is, a saját metódusaikkal és tagváltozóikkal. Még a modulok is objektumokként vannak kezelve miután be lettek töltve. Így a python a kódolási stílusban nem feltétlenül objektum-orientált, de megvalósításban az.

Speciális metódusok

Mint láttuk korábban, az __init__() metódusnak speciális szerepe van, ez a konstruktor. Vannak még más ilyen speciális nevek, amiknek speciális szerepe van az objektumban. Egyik ilyen az __str__(), ami azt mondja meg hogy hogyan lehet az objektumot karakterlánccá konvertálni, hogyan lehet print-elni. Például így lehetne ezt a Targy osztályunknál megvalósítani:

link

Általánosságban a két alulvonással kezdődő nevek le vannak foglalva, hogy a python nyelv beépített dolgaira lehet csak őket használni, úgyhogy ti ne nevezzetek el úgy magatoknak dolgokat! (Bár gondolom nem állt szándékotokban.)

A python hivatalos dokumentációban itt megtalálható az összes ilyen speciális név. Számunkra még esetleg érdekes lehet:

  • a __len__(), ami megmondja, hogy a len(targy) mit adjon vissza
  • a __cmp__(), ami megmondja hogy hogyan kell két ilyen objektumot összehasonlítani, tehát azt, hogy melyik számítson kisebbnek/nagyobbnak sorbarendezéskor
  • az __add__(), ami megmondja hogy annak hogy targy1 + targy2 mi legyen az eredménye. (Tantárgyak esetén ennek persze nincs értelme.)
Személyes eszközök