Python – objektumorientált

Hirdetések

A Python létezése óta objektumorientált nyelv. Emiatt az osztályok és objektumok létrehozása és használata egyenesen egyszerű. Ez a fejezet segít abban, hogy szakértővé váljon a Python objektumorientált programozási támogatásának használatában.

Ha nincs korábbi tapasztalata az objektumorientált (OO) programozással kapcsolatban, érdemes egy bevezető kurzust vagy legalább valamilyen oktatóanyagot felkeresnie, hogy tisztában legyen az alapfogalmakkal.

Mindamellett itt van egy kis bevezető az objektumorientált programozásról (OOP), hogy felgyorsuljon –

Áttekintés az OOP terminológiájáról

  • osztály – Egy objektum felhasználó által meghatározott prototípusa, amely meghatározza az osztály bármely objektumát jellemző attribútumok halmazát. Az attribútumok adattagok (osztályváltozók és példányváltozók) és metódusok, amelyekhez pontjelöléssel lehet hozzáférni.

  • osztályváltozó – Olyan változó, amelyet egy osztály minden példánya megoszt. Az osztályváltozókat egy osztályon belül, de az osztály bármely metódusán kívül definiáljuk. Az osztályváltozókat nem használják olyan gyakran, mint a példányváltozókat.

  • Adattag – Olyan osztályváltozó vagy példányváltozó, amely egy osztályhoz és annak objektumaihoz kapcsolódó adatokat tárol.

  • Funkciótúlterhelés – Egynél több viselkedés hozzárendelése egy adott függvényhez. Az elvégzett művelet az érintett objektumok vagy argumentumok típusa szerint változik.

  • Instance változó – Egy metóduson belül definiált változó, amely csak egy osztály aktuális példányához tartozik.

  • Öröklés – Egy osztály tulajdonságainak átadása más, tőle származtatott osztályokra.

  • Instance – Egy adott osztály egyedi objektuma. A Circle osztályhoz tartozó obj objektum például a Circle osztály példánya.

  • Instanciálás – Egy osztály példányának létrehozása.

  • Módszer – Egy osztálydefinícióban meghatározott speciális típusú függvény.

  • Objekt – Egy adatszerkezet egyedi példánya, amelyet az osztálya határoz meg. Egy objektum egyaránt tartalmaz adattagokat (osztályváltozókat és példányváltozókat) és metódusokat.

  • Operátor-túlterhelés – Egynél több függvény hozzárendelése egy adott operátorhoz.

Osztályok létrehozása

A class utasítás új osztálydefiníciót hoz létre. Az osztály neve közvetlenül a class kulcsszó után következik, amelyet kettőspont követ az alábbiak szerint –

class ClassName: 'Optional class documentation string' class_suite
  • Az osztály rendelkezik egy dokumentációs karakterlánccal, amely a ClassName.__doc__ segítségével érhető el.

  • A class_suite az osztály tagjait, adatattribútumait és függvényeit definiáló összes komponens utasításból áll.

Példa

A következő egy egyszerű Python osztály példája –

class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
  • Az empCount változó egy olyan osztályváltozó, amelynek értéke az osztály összes példánya között közös. Ezt Employee.empCount néven lehet elérni az osztályon belülről vagy az osztályon kívülről.

  • Az első metódus __init__() egy speciális metódus, amelyet osztálykonstruktornak vagy inicializáló metódusnak nevezünk, amelyet a Python akkor hív meg, amikor létrehozzuk ennek az osztálynak egy új példányát.

  • A többi osztálymetódust normál függvényekhez hasonlóan deklaráljuk, azzal a különbséggel, hogy az egyes metódusok első argumentuma a self. A Python a self argumentumot hozzáadja helyetted a listához; a metódusok hívásakor nem kell megadnod.

Példányobjektumok létrehozása

Az osztály példányainak létrehozásához az osztályt az osztálynévvel hívod meg, és átadod az __init__ metódus által elfogadott argumentumokat.

"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)

A Attribútumok elérése

Az objektum attribútumaihoz az objektummal a pontoperátor segítségével férsz hozzá. Az osztályváltozót az osztálynévvel érnénk el a következőképpen –

emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount

Most, az összes fogalmat összerakva –

#!/usr/bin/pythonclass Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount

A fenti kód végrehajtásakor a következő eredményt kapjuk –

Name : Zara ,Salary: 2000Name : Manni ,Salary: 5000Total Employee 2

Elhelyezhetjük, eltávolíthatjuk, vagy módosíthatja az osztályok és objektumok attribútumait bármikor –

emp1.age = 7 # Add an 'age' attribute.emp1.age = 8 # Modify 'age' attribute.del emp1.age # Delete 'age' attribute.

Az attribútumok eléréséhez a szokásos utasítások helyett a következő függvényeket használhatja –

  • A getattr(obj, name) – az objektum attribútumának eléréséhez.

  • The hasattr(obj,name) – egy attribútum létezésének ellenőrzésére.

  • The setattr(obj,name,value) – egy attribútum beállítására. Ha az attribútum nem létezik, akkor létrejön.

  • A delattr(obj,name) – egy attribútum törlése.

hasattr(emp1, 'age') # Returns true if 'age' attribute existsgetattr(emp1, 'age') # Returns value of 'age' attributesetattr(emp1, 'age', 8) # Set attribute 'age' at 8delattr(empl, 'age') # Delete attribute 'age'

Beépített osztályattribútumok

Minden Python osztály a következő beépített attribútumokat tartja, és ezek a pont operátorral érhetők el, mint bármely más attribútum –

  • __dict__ – Az osztály névterét tartalmazó szótár.

  • __doc__ – Az osztály dokumentációs karakterlánca vagy nincs, ha nem definiált.

  • __name__ – Az osztály neve.

  • __module__ – A modul neve, amelyben az osztály definiálva van. Ez az attribútum interaktív módban a “__main__”.

  • __bases__ – Egy esetleg üres tuple, amely az alaposztályokat tartalmazza, az alaposztályok listájában való előfordulásuk sorrendjében.

A fenti osztály esetében próbáljuk meg elérni ezeket az attribútumokat –

#!/usr/bin/pythonclass Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salaryprint "Employee.__doc__:", Employee.__doc__print "Employee.__name__:", Employee.__name__print "Employee.__module__:", Employee.__module__print "Employee.__bases__:", Employee.__bases__print "Employee.__dict__:", Employee.__dict__

A fenti kód végrehajtásakor a következő eredményt kapjuk –

Employee.__doc__: Common base class for all employeesEmployee.__name__: EmployeeEmployee.__module__: __main__Employee.__bases__: ()Employee.__dict__: {'__module__': '__main__', 'displayCount':<function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}

Objektumok megsemmisítése (Garbage Collection)

Aython automatikusan törli a nem szükséges objektumokat (beépített típusok vagy osztálypéldányok), hogy felszabadítsa a memóriaterületet. Azt a folyamatot, amellyel a Python periodikusan visszaköveteli a már nem használt memóriablokkokat, szemétgyűjtésnek nevezzük.

A Python szemétgyűjtője a program végrehajtása közben fut, és akkor lép működésbe, amikor egy objektum hivatkozási száma eléri a nullát. Egy objektum hivatkozási száma akkor változik, amikor a rá mutató aliasok száma változik.

Egy objektum hivatkozási száma akkor nő, amikor új nevet kap, vagy egy tárolóba (lista, tuple vagy szótár) kerül. Az objektum hivatkozásainak száma csökken, amikor az objektumot a del segítségével töröljük, a hivatkozását újra hozzárendeljük, vagy a hivatkozása kikerül a hatóköréből. Amikor egy objektum hivatkozási száma eléri a nullát, a Python automatikusan begyűjti azt.

a = 40 # Create object <40>b = a # Increase ref. count of <40> c = # Increase ref. count of <40> del a # Decrease ref. count of <40>b = 100 # Decrease ref. count of <40> c = -1 # Decrease ref. count of <40> 

Normális esetben nem vesszük észre, amikor a szemétgyűjtő megsemmisíti az elárvult példányt, és visszaköveteli a helyét. De egy osztály implementálhatja a __del__() speciális metódust, az úgynevezett destruktort, amelyet akkor hív meg, amikor a példány megsemmisülni készül. Ez a metódus használható a példány által használt nem memóriaforrások kitakarítására.

Példa

Ez a __del__() destruktor kiírja a megsemmisítés előtt álló példány osztálynevét –

#!/usr/bin/pythonclass Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed"pt1 = Point()pt2 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejctsdel pt1del pt2del pt3

A fenti kód végrehajtásakor a következő eredményt kapjuk –

3083401324 3083401324 3083401324Point destroyed

Megjegyzés – Ideális esetben az osztályokat külön fájlban definiáljuk, majd import utasítással importáljuk őket a fő programfájlba.

Osztály öröklése

Ahelyett, hogy a nulláról kezdenénk, létrehozhatunk egy osztályt úgy, hogy egy már létező osztályból származtatjuk azt úgy, hogy az új osztály neve után zárójelben felsoroljuk a szülőosztályt.

A gyermekosztály örökli a szülőosztály attribútumait, és ezeket az attribútumokat úgy használhatjuk, mintha a gyermekosztályban lennének definiálva. A gyermekosztály felülbírálhatja a szülő osztály adattagjait és metódusait is.

Szintaktika

A származtatott osztályok deklarálása hasonlóan történik, mint a szülő osztályé; azonban az osztály neve után megadjuk az öröklendő bázisosztályok listáját –

class SubClassName (ParentClass1): 'Optional class documentation string' class_suite

Példa

#!/usr/bin/pythonclass Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttrclass Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method'c = Child() # instance of childc.childMethod() # child calls its methodc.parentMethod() # calls parent's methodc.setAttr(200) # again call parent's methodc.getAttr() # again call parent's method

A fenti kód végrehajtásakor a következő eredményt kapjuk –

Calling child constructorCalling child methodCalling parent methodParent attribute : 200

Hasonló módon vezethetünk egy osztályt több szülőosztályból az alábbiak szerint –

class A: # define your class A.....class B: # define your class B.....class C(A, B): # subclass of A and B.....

Az issubclass() vagy az isinstance() függvények segítségével két osztály és példányok kapcsolatát ellenőrizhetjük.

  • Az issubclass(sub, sup) bólusú függvény igazat ad vissza, ha az adott alosztály sub valóban a szuperosztály sup alosztálya.

  • Az isinstance(obj, Class) boolean függvény igazat ad vissza, ha obj a Class osztály példánya vagy a Class egy alosztályának példánya

Módszerek felülírása

A szülőosztály metódusait mindig felülírhatjuk. A szülő osztály metódusainak felülbírálásának egyik oka, hogy az alosztályodban különleges vagy eltérő funkcionalitást akarhatsz.

Példa

#!/usr/bin/pythonclass Parent: # define parent class def myMethod(self): print 'Calling parent method'class Child(Parent): # define child class def myMethod(self): print 'Calling child method'c = Child() # instance of childc.myMethod() # child calls overridden method

A fenti kód végrehajtásakor a következő eredményt kapod –

Calling child method

Bázis metódusok felülbírálása

A következő táblázatban néhány olyan általános funkcionalitás szerepel, amelyet felülbírálhatsz a saját osztályodban –

Sz.sz. Módszer, leírás & Példahívás
1

__init__ ( self )

Konstruktor (bármilyen választható argumentummal)

Példahívás : obj = className(args)

2

__del__( self )

Destruktor, törli az objektumot

Példahívás : del obj

3

__repr__( self )

Egy értékelhető string ábrázolása

Példahívás : repr(obj)

4

__str__( self )

Nyomtatható string ábrázolás

Példahívás : str(obj)

5

__cmp__ ( self, x )

Object comparison

Sample Call : cmp(obj, x)

Operátorok túlterhelése

Tegyük fel, hogy létrehoztunk egy Vector osztályt kétdimenziós vektorok ábrázolására, mi történik, ha a plus operátorral összeadjuk őket? Valószínűleg a Python kiabálni fog veled.

Az __add__ metódust azonban definiálhatod az osztályodban a vektorok összeadásához, és akkor a plusz operátor az elvárásoknak megfelelően viselkedik –

Példa

#!/usr/bin/pythonclass Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b)v1 = Vector(2,10)v2 = Vector(5,-2)print v1 + v2

A fenti kód végrehajtásakor a következő eredményt kapjuk –

Vector(7,8)

Adatok elrejtése

Egy objektum attribútumai lehetnek vagy nem lehetnek láthatóak az osztály definícióján kívül. Az attribútumokat kettős aláhúzás előtaggal kell elnevezni, és ezek az attribútumok ezután nem lesznek közvetlenül láthatóak kívülállók számára.

Példa

#!/usr/bin/pythonclass JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCountcounter = JustCounter()counter.count()counter.count()print counter.__secretCount

A fenti kód végrehajtásakor a következő eredményt kapjuk –

12Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'

Aython úgy védi ezeket a tagokat, hogy belsőleg megváltoztatja a nevet, hogy tartalmazza az osztály nevét. Az ilyen attribútumok elérhetők az object._className__attrName. Ha az utolsó sorodat a következőre cserélnéd, akkor ez neked is működik –

.........................print counter._JustCounter__secretCount

A fenti kód végrehajtásakor a következő eredményt kapod –

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.