Felhasználói eszközök

Eszközök a webhelyen


oktatas:programozas:python:python_oop

< Python

Python Objektum Orientált Programozás

Osztály

Tároljuk el egy dolgozó, nevét, a települést ahol lakik, és az életkorukat. A feladat a következő UML diagrammal ábrázolható.

Az osztályt a class kulcsszóval vezetjük be. A class után az osztály neve következik, amit egy kettőspont (:) követ.

dolgozo.py
class Dolgozo:
    nev = 'Névtelen'
    telepules = 'Ismertelen'
    kor = 0
 
janos = Dolgozo
 
janos.nev = 'Nagy János'
janos.telepules = 'Szolnok'
janos.kor = 35
 
print('{}\n{}\n{}'.format(
    janos.nev, 
    janos.telepules, 
    janos.kor
    ))

Metódusok

class Dolgozo:
	Nev = "Névtelen"
	def beallitNev(self, atvettNev):
		self.Nev = atvettNev
	def lekerNev(self):
		return self.Nev
 
Joska = Dolgozo()
Joska.beallitNev("Nagy József")
print Joska.lekerNev()

Az osztály metódusait a def kulcsszó vezeti be.

Minden metódus első paramétere egy speciális paraméter, mivel ez mindig automatikusan értéket kap, mindig a létrejött objektumra mutat automatikusan. Elnevezése tetszőleges, de szokásosan self.

Ha öröklést használunk, az osztály neve után meg kell adni zárójelben az ősosztály nevét. Ha nincs öröklésre jelölt ősosztály (vagy szuper osztály), akkor a zárójeleket elszokás hagyni; de szintaktikailag nem hibás leírni.

Konstruktor

A konstruktor az osztály adattagjainak előkészítésére való. Egy speciális metódus, amely egy objektum létrehozásakor kerül meghívásra.

A Python nyelven a konstruktort egy init() nevű metódus. Az első paraméter itt is a self.

kon.py
class Dolgozo:
    def __init__(self):
        self.nev = 'Névtelen'
        self.Kor = 0
        self.nem = 'ismeretlen'
 
 
janos = Dolgozo()
 
janos.nev = 'Nagy János'
janos.kor = 35
janos.nem = 'férfi'
 
print(janos.nev)
print(janos.kor)
print(janos.nem)

A konstruktornak paraméterként átadhatók az adattagok kezdőértékei.

class Dolgozo:
	def __init__ (self, nev, kor, nem):
		self.Nev = nev
		self.Kor = kor
		self.Nem = nem
	def lekerKor(self):
		return self.Kor
 
Joska = Dolgozo("Nagy József", 25, "f")
print Joska.Kor

Több alakú konstruktor

class Dolgozo:
	def __init__ (self, nev='névtelen', kor=0, nem='semleges'):
		self.nev = nev
		self.kor = kor
		self.nem = nem
 
joska = Dolgozo("Nagy József", 25, "f")
janos = Dolgozo()
lajos = Dolgozo(kor=32)

Öröklés

Az öröklés esetén az ősosztályt az osztály neve után adjuk meg. A példánkban az ősosztályt a Dolgozo, amit szeretnénk a Mernok osztályban örökíteni. Ezért így kezdem a Mernok osztály leírását:

class Mernok(Dolgozo):
class Dolgozo: 
	def __init__(self):
		self.Nev="Névtelen"
	def lekerNev(self):
		return self.Nev
	def beallitNev(self, atvettNev):
		self.Nev = atvettNev
 
class Mernok(Dolgozo):
	def __init__(self):
		self.Diploma = "Ismeretlen"
	def lekerDiploma(self):
		return self.Diploma
 
Joska = Dolgozo()
#Joska.beallitNev("Kis József")
print Joska.lekerNev()
 
Tibi = Mernok()
print Tibi.lekerDiploma()
Tibi.beallitNev("Nagy Tibor")
print Tibi.lekerNev()

A super() metódus

A super() metódus lehetővé teszi, hogy a szuper osztály eredeti metódusait meghívjuk.

Vegyünk egy Dolgozo osztályt, amely a munkát úgy szemlélteti, hogy a képernyőre írja az 'ások' szót. A dolgozó osztályból készítünk egy Mernok osztályt. A munka() metódust, most felülírjuk, ezzel mert a mérnök mér. Ezt úgy látjuk, hogy kiírja a program, hogy 'mérek'. Ha mégis szükség lenne arra, hogy a Mernok osztályból meg tudjuk hívni a Dolgozo osztály munka() metódusát, akkor azt a super() metóduson keresztül tudjuk megtenni:

class Dolgozo:
    def munka(self):
        print('ások')
 
class Mernok(Dolgozo):
    def munka(self):
        print('mérek')
    def asas(self):
        super().munka()
 
joska = Mernok()
joska.asas()

Statikus adattagok

Statikus tag:

class Valami():
    EGY=0
    KETTO=1
    def valami(self):
        if self.EGY:
            print('egy')

Másik osztályban így használhatom a statikus tagokat:

Valami.EGY

Példány, osztály és statikus metódus

Egy osztályban háromféle metódust hozhatunk létre:

class Mycalss:
    def my_method(self):
        return 'példánymetódus hívása', self
 
    @classmethod
    def my_classmethod(cls):
        return 'osztálymetódus hívása', cls
 
    @staticmethod
    def my_staticmethod():
        return 'statikus metódushívás'

Példány metódus

A példánymetódus, egy általános példánymetódus. A példánymetódusok egy önmagukra mutató paramétert igényel, de megadhatók más paraméterek is.

A self paraméteren keresztül a példánymetódusok szabadon elérhetik az adattagokat (attribútumok), és más metódusokat, ugyanazon az objektumon. Így könnyen módosítható az objektum állapota.

Osztálymetódus

Az osztálymetódust a classmethod dekorátorral kell megjelölni. A self paraméter helyet az osztálymetódusok egy cls paramétert használnak, amely az osztályra mutat és nem az objektumpéldányra, amikor meghívásra kerül.

Mivel az osztálymetódus csak a cls argumentumhoz fér hozzá, ezért nem módosíthatja az objektum állapotát. Az osztálymetódusok, azonban továbbra is módosíthatják az osztály állapotát, amely az osztály összes példányára érvényes.

Statikusmetódus

A statikusmetódusokat a staticmethod dekorátorral kell megjelölni. Az ilyen metódus nem veszi figyelembe sem a self, sem a cls paramétert, de lehet tetszőleges számú más paramétere.

A statikusmetódus nem módosíthatja sem az objektum, sem az osztály állapotát.

Statikus metódus példa

Saját matematikai osztály:

math.py
class Math:
    @staticmethod
    def abs(x):
        if x >= 0:
            return x
        else:
            return x * -1
 
    @staticmethod
    def pow(a, b):
        if b == 0:
            return 1
        if b == 1:
            return a
        tmp = 1
        for i in range(b):
            tmp *= a
        return tmp
 
 
print(Math.abs(-9))
print(Math.pow(8, 2))

Kivételkezelés

Finally nélkül

olvas.py
def tryReadfile():
    fp = open('adat.txt', 'r', encoding='utf-8')
    lista = fp.read().splitlines()
    fp.close()
    return lista
 
def readfile():
    try:
        return tryReadfile()
    except:
        print('Hiba! A fájl olvasása sikertelen!')
 
print(readfile())

Finally-val

olvas.py
def tryReadfile():
    fp = open('adat.txt', 'r', encoding='utf-8')
    lista = fp.read().splitlines()
 
    datas = []
    datas.append(lista)
    datas.append(fp)
    return datas
 
def readfile():
    try:
        datas = tryReadfile()
        lista = datas[0]
        fp = datas[1]
        return lista
    except:
        print('Hiba! A fájl olvasása sikertelen!')
    finally:
        fp.close()
 
print(readfile())

Konstruktor túlterhelése

A Python nyelven a konstruktorból csak egyet írhatok, nincs valódi túlterhelés.

Ha szeretnénk többféle paraméterrel használni, akkor a paramétereknek kezdő értéket kell adni. Így a paraméterek megadása nem kötelező.

main.py
class Dolgozo:
 
    def __init__(self, atvettNev='Névtelen', atvettTelepules='ismeretlen'):
        self.nev = atvettNev
        self.telepules = atvettTelepules
 
janos = Dolgozo()
print(janos.nev)
 
mari = Dolgozo('Pere Mária', 'Szeged')
print(mari.nev)

Konstruktor túlterhelése gyártómetódussal

A konstruktorok túlterhelésére a paraméterek kezdőértékénél tisztább megoldást kínál a gyártómetódus használata.

gyarto.py
class Dolgozo:
 
    def __init__(self, atvettNev: str, atvettTelepules: str):
        self.nev = atvettNev
        self.telepules = atvettTelepules
    @classmethod
    def gen(cls):
        return cls(atvettNev='Névtelen', atvettTelepules='ismeretlen')
 
janos = Dolgozo.gen()
print(janos.nev)
 
 
mari = Dolgozo('Pere Mária', 8)
print(mari.nev)

Felhasznált webhely:

Metódusok túlterhelése

Ha szeretnék olyan metódust írni, amit többféle képen is lehet paraméterezni adhatunk a paramétereknek kezdőértéket.

metodus.py
class Dolgozo:
 
    def __init__(self, atvettNev, atvettTelepules):
        self.nev = atvettNev
        self.telepules = atvettTelepules
 
    def beallit(self, atvettNev='Névtelen', 
            atvettTelepules='ismeretlen'):
        self.nev = atvettNev
        self.telepules = atvettTelepules
 
 
mari = Dolgozo('Pere Mária', 'Szeged')
print(mari.nev, ' ', mari.telepules)
 
mari.beallit('Park Mária')
print(mari.nev, ' ', mari.telepules)
 
mari.beallit('Park Mária', 'Szolnok')
print(mari.nev, ' ', mari.telepules)

A multipledispatch modul

Másik megoldás lehet a multipledispatch modul használata. A használathoz a modult telepíteni szükséges:

pip3 install multipledispatch
dispatch.py
from multipledispatch import dispatch
 
class Dolgozo:
 
    def __init__(self, atvettNev, atvettTelepules):
        self.nev = atvettNev
        self.telepules = atvettTelepules
 
    @dispatch(str)
    def beallit(self, atvettNev):
        self.nev = atvettNev
 
    @dispatch(str, str)
    def beallit(self, atvettNev, atvettTelepules):
        self.nev = atvettNev
        self.telepules = atvettTelepules
 
mari = Dolgozo('Pere Mária', 'Szeged')
print(mari.nev, ' ', mari.telepules)
 
mari.beallit('Park Mária')
print(mari.nev, ' ', mari.telepules)
 
mari.beallit('Park Mária', 'Szolnok')
print(mari.nev, ' ', mari.telepules)

Interfész

A Python nyelv nem támogatja.

De van néhány modul, amivel hasonló megvalósítható.

  • interface
  • abc

interface

main.py
from interface import Interface, implements
 
class iPelda(Interface):
    def valami(self):
        pass
 
class Mas(implements(iPelda))
    def valami(self):
        print('Működik')

Külső linkek

oktatas/programozas/python/python_oop.txt · Utolsó módosítás: 2021/12/19 12:34 szerkesztette: admin