Objektno programiranje v Pythonu

Razredi in objekti

Objekt je skupek podatkov in metod (funkcij), s katerimi dostopamo do podatkov. Primeri:

Skratka, z objekti podatke organiziramo v smiselne uporabne enote.

Objekt torej v sebi hrani podatke, ki jim pravimo tudi atribitute (attribute), včasih pa tudi polja (fields) ali komponente (components). Na primer, objekt, ki predstavlja točkasto telo, bi lahko imel atribute masa, x, y, vx in vy.

Do atributa a v objektu o dostopamo z o.a.

Metodo m na objektu o pokličemo z o.m(...).

Običajno imamo več objektov iste vrste, na primer za vsako točkasto telo v simulaciji en objekt. V ta namen definiramo razred, ki so opisuje objekte iste vrste. Vsaj objekt torej pripada nekemu razredu.

Definicija razreda

V Pythonu definiramo razred takole:

class ImeRazreda():
   """Dokumentacija o razredu"""

   def __init__(self, ....):
       """Posebna metoda (konstruktor), ki se pokliče, ko se ustvari nov objekt."""
       ...

   def __repr__(self):
       """Metoda, ki pretvori objekt v niz, ki ga predstavlja."""
       ....

   def __str__(self):
       """Metoda, ki pretvori objekt v uporabniku prijazen niz."""
       ....

   # Ostale metode

   def metoda1(self, ....):
       "Moja prva metoda"
       ....

   def metoda2(self, ....):
       "Moja druga metoda"
       ....

   ...

Nov objekt razreda MojRazred naredimo z izrazom MojRazred(....). Naredi se nov objekt in na njem se pokliče metoda __init__(self, ...) (pravimo ji konstruktor), pri čemer je self novonastali objekt.

Objektna metoda vedno sprejme prvi argument self, to je objekt, na katerem se izvaja.

Poznamo tudi statične metode. Te ne delujejo na objektih, ampak so samo definirane znotraj razreda. Za primer glej metodo gcd v ulomek.py..

Oglejmo si primera ulomek.py in delec.py.

Imenovani nabori

Včasih potrebujemo zelo preproste objekte, ki v atributih hranijo podatke, nimajo po definiranih nobenih metod. Seveda lahko v ta namen definiramo razred. Vendar pa knjižnica collections ponuja tudi elegantno rešitev imenovane nabore (named tuples). Več o tem najdete v dokumentaciji o namedtuple in v primeru ocene.py.

Iteratorji in generatorji

Iteratorji so posebni objekti, ki jih uporabljamo za pregledovanje tabel, datotek, in ostalih zbirk podatkov. Kot predpisuje dokumenatacija za iterator, je to objekt ki ima:

Mnogi objekti niso iteratorji (tabela, nabor, slovar, niz, datoteka, …), ampak lahko vrnejo iterator, ki našteje elemente, ki jih vsebujejo, glej dokumentacijo za iterable. Tak mora imeti metodo __iterable__, ki vrne iterator. Pravimo, da je objekt iterabilen.

Če imamo iterabilen objekt o, lahko pregledamo njegove elemente z zanko for. Koda

for x in o:
  ...

je ekvivalentna kodi:

it = iter(o)
while True:
  try:
    x = next(it)
    ...
  except StopIteration:
    break

Nekatere najbolj uporabne iteratorje najdete v knjižnici itertools.

Generator je posebna funkcija, ki namesto return uporablja yield. To v resnici ni funkcija, ampak poseben mehanizem v Pythonu, s katerim elegantno naredimo iterator. Če je g generator, ob klicu g(...) dobimo pripadajoči iterator, ki vrača elemente, ki jih generira g z ukazom yield. Takole bi naredili range kot generator, če ga še ne bi imeli:

def mojRange(a, b):
    """Generator, ki generira vsa cela števila med a in b."""
    while a < b:
        yield a
        a = a + 1