#!/usr/bin/env python # coding: utf-8 # # 8. előadás # _Tartalom:_ osztályok, objektum orientált programozás # # # A Python objektum orientált programozást a 2D-s pontok osztályának elkészítésén keresztül mutatjuk be _(Nagyban támaszkodni fogunk Siki Zoltán könyvére)_. A Python nyelvben minden osztály (például a lista vagy a szótár is, de a függvények is). # Kezdjük is el az osztály kódjának elkészítését. # # # In[1]: # Siki Zoltán class Point2D(object): # object a bázis osztály """ kettő dimenziós pontok osztálya """ def __init__(self, east = 0, north = 0): # __init__ a konstruktor """ Initialize point :param east: első koordináta :param north: második koordináta """ #self.east = east # tagváltozó létrehozása self.setEast(east) #self.north = north self.setNorth(north) def abs(self): """ calculate length of vector (absolute value) :returns: absolute value """ return (self._east**2 + self._north**2)**0.5 def __str__(self): """ String representation of the 2D point :returns: point coordinates as string (e.g. 5; 3) """ return "*%.3f; %.3f*" % (self._east, self._north) def __add__(self, p): """ Add two point :param p: point to add :returns: the sum of the two point (vector) """ return Point2D(self._east + p.getEast(), self._north + p.getNorth()) def setEast(self, east): self._east = east def getEast(self): return self._east def setNorth(self, north): if north < 400000: self._north = north else: raise ValueError('north must be less than 400000') def getNorth(self): return self._north # A `self` változó az osztály minden (nem statikus vagy osztály) metódusának az első paramétere és az objektum példányt jelenti, ezen keresztül hivatkozhatunk az objektum elemeire pl. `self.east`. A többsoros megjegyzés a sphinx programnak megfelelően készült, hogy automatikusan lehessen dokumentációt generálni a kódból. # Próbáljuk ki a kódunkat. # In[2]: p0 = Point2D() # példányosítás, 2, 0 pont p1 = Point2D(0) # példányosítás, 0, 0 pont p2 = Point2D(2, -2) # példányosítás, 2,–2 pont # Írassuk ki az egyes pontok tagváltozóit, abszolút értékét. # In[3]: pontok = [p0, p1, p2] for pont in pontok: print("[%2d,%2d] abs: %.2f" % (pont.getEast(), pont.getNorth(), pont.abs())) # In[4]: print("p2 east tagváltozó értéke: ", p2.getEast()) print("p2 north tagváltozó értéke: ", p2.getNorth()) print("p2 abs() függvény értéke: ", p2.abs()) print("p2.__dict__:", p2.__dict__) print("p2:", p2) # Az egyes osztályokhoz speciális függvényeket definiálhatunk (mint pl. az `__init__`), ezek jellemzője, hogy két aláhúzás karakterrel kezdődik és végződik a nevük. # # Az `__init__` függvény az úgynevezett **konstruktor**, ez fut le a példányok létrehozásakor, itt biztosíthatjuk, hogy ne legyen inicializálatlan tagváltozónk. # # A **destruktor**t a `__del__` függvény implementálásával valósíthatjuk meg. A dinamikus tárfoglalás hiányában a Pythonban erre # ritkábban van szükség. # # A print utasítás az osztály `__str__` metódusát hívja meg. A fenti példában ennek alapértelmezett változatának eredményét láthattuk az object osztályból. # In[5]: p2 # In[6]: print(p2) # In[7]: p3 = Point2D(10, 300000) print(p3) # A pont osztály egy példányának a koordinátáit közvetlenül nem változtathatjuk meg amennyiben: # ``` python # self.east = east # ``` # helyett a # ``` python # self.setEast(east) # ``` # módon hozzuk létre tagváltozóinkat. # Ha a pont osztály egy példányának a koordinátáit közvetlenül megváltoztathatjuk, ez azzal a következménnyel járhat, hogy: # 1. a példány tagváltozóit az osztály felhasználója egy programhibából következően is átírhatja, # 2. a példány tagváltozóit ellenőrzés nélkül is felül lehet írni. # # Ennek kivédésére privát tagváltozókat (`_` karakterrel kezdődő név) és getter/setter metódusokat használhatunk. Írjuk át az osztályunkat, hogy egy-egy metóduson keresztül lehessen megváltoztatni a tagváltozókat. A Python osztályok privát tagváltozóinak neve aláhúzás karakterrel kezdődik. A két aláhúzással kezdődő és végződő nevek a Python nyelv elemei. # # A következő kódrészlet # ``` python # def setNorth(self, north): # if north < 400000: # self._north = north # else: # raise ValueError('north must be less than 400000') # ``` # miatt a # # ``` python # p3.setNorth(400000) # ``` # illetve # ``` python # p9 = Point2D(10, 400001) # ``` # # esetén a következő hibába botlanánk: # ``` python # ValueError Traceback (most recent call last) # ValueError: north must be less than 400000 # ``` # A Python nyelvben az osztályokhoz további speciális függvényekkel műveleteket is definiálhatunk. A pontokat mint helyvektorokat is használhatjuk, készítsük el a helyvektorok összeadását. # # ``` python # def __add__(self, p): # """ Add two point # :param p: point to add # :returns: the sum of the two point (vector) # """ # return Point2D(self.east + p.east, self._north + p._north) # ``` # # Próbáljuk ki: # In[8]: print(p2) print(p3) print("Összegük: ", p2 + p3) # ### _Used sources_ / Felhasznált források # - [Shannon Turner: Python lessons repository](https://github.com/shannonturner/python-lessons) MIT license (c) Shannon Turner 2013-2014 # - [Siki Zoltán: Python mogyoróhéjban](http://www.agt.bme.hu/gis/python/python_oktato.pdf) GNU FDL license (c) Siki Zoltán