120 likes | 282 Views
Python - OOP. Zgled tvorbe razreda. Posplošeno Fibonaccijevo zaporedje. Fibonaccijevo zaporedje: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
E N D
Python - OOP Zgled tvorbe razreda
Posplošeno Fibonaccijevo zaporedje • Fibonaccijevo zaporedje: • 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... • Fibonaccijeva števila definiramo z začetnima pogojema (prvo in drugo število sta enaka 1) ter z rekurzivno formulo (n-to Fibonaccijevo število je vsota prejšnjih dveh) . S temi podatki lahko izračunamo vsa ostala števila. • F1 = 1 • F2 = 1 • Fn = Fn-1 + Fn-2 • Če začetna pogoja spremenimo (rekurzivno pravilo pa ostane isto), dobimo posplošena Fibonaccijeva števila. Če si npr. za prvo število izberemo 3 in za drugo -1 dobimo zaporedje števil 3, -1, 2, 1, 3, 4, 7, 11... • F1 = a • F2 = b • Fn = Fn-1 + Fn-2
Posplošeno Fibonaccijevo zaporedje • Razred PosploseniFibonacci, ki bo vseboval metodo vrniNto(n), ki bo izračunal n-to posplošeno Fibonaccijevo število. • Način uporabe konstruktorja (metode __init__): • PosploseniFibonacci() - ta naj za začetni pogoj postavi pogoj za običajna Fibonaccijeva števila. • PosploseniFibonacci(prvo, drugo) - temu podamo vrednosti prvega in drugega posplošenega Fibonaccijevega števila. • Če torej ustvarimo objekta fibo = PosploseniFibonacci() in splosni = PosploseniFibonacci(3, -1) nam klica metod fibo.vrniNto(4) in splosni.vrniNto(4) vrneta 3 oz. 1. • 1, 1, 2, 3 • 3, -1, 2, 1
Konstruktor • Hraniti bo potrebno začetna člena classPosploseniFibonacci : def __init__(self, p = 1, d = 1) : self._prvo = p self._drugo = d • Zakaj podčrtaj pri _prvo? • Filozofija Python-a je, da nič ni prepovedano • Če nekdo želi, naj programira "grdo" • Neposredno dostopa do lastnosti (komponent) objektov • Z _ povemo, da ni mišljeno, da bi uporabniki neposredno dostopali do te komponente • Mi tega v glavnem ne bomo uporabljali (a bomo kljub temu delali z metodami get/set) • Tako kot z _ _ (__init__, __str__, __repr__) povemo, da naj se ta metoda ne bi klicala neposredno • Čeprav lahko! • zeko = MojaKnj.Zajec() • zeko.masa = 3 • zeko.__init__() # GRDO!!!!! (a dovoljeno)
Metoda def vrniNto(self, n) : if n == 1 : return self._prvo if n == 2 : return self._drugo return self.vrniNto(n – 2) + self.vrniNto(n – 1)
Povečajmo učinkovitost • Zelo pogosto potrebujemo prvih 20 členov Fibonnacijevega zaporedja, ostala pa bolj redko • Kaj storiti, da izboljšamo odzivnost? • Naj objekt hrani še seznam prvih 20 členov, Če potem uporabimo vrniNto(i) in je i <= 20, le pogledamo v seznam. • Kje narediti tabelo – v konstruktorju!
Spremenjeni konstruktor • Hraniti bo potrebno tabelo prvih 20 členov class PosploseniFibonacci : def __init__ (self, p = 1, d = 1) : self._tabela = [p, d] for i in range (2, 21) : self._tabela.append(self._tabela[i – 2] + self._tabela[i - 1])
Vrni Nto def vrniNto(self, n) : if n <= 20 : return self.tabela[n] return self.vrniNto(n – 2) + self.vrniNto(n – 1) • In sedaj bo zelo zoprno, če bo kdo "zunaj" naredil • zap._prvi = 5 • in seveda pozabil popraviti tabelo
Nastavi začetni člen defnastaviZačetni(self, noviPrvi = 1, noviDrugi = self._drugi) : self._prvi = noviPrvi self._drugi = noviDrugi self._tabela = [self._prvi, self._drugi] for i in range (2, 21) : self._tabela.append(_tabela[i – 2] + _tabela[i - 1]) File "E:\PrJ\OOP\knjiznicaMat.py", line 11, in PosploseniFibonacci defnastaviZačetni(self, noviPrvi = 1, noviDrugi = self._drugi) : NameError: name 'self' is not defined self v času definicije še ne poznamo, zato self._drugi ne gre
Nastavi začetni člen def nastaviZačetni(self, noviPrvi = 1,noviDrugi = None) : if noviDrugi == None : noviDrugi = self._drugi self._prvi = noviPrvi self._drugi = noviDrugi self._tabela = [self._prvi, self._drugi] for i in range (2, 21) : self._tabela.append(self._tabela[i – 2] + self._tabela[i - 1]) 10
Kaj pa povej začetna čena? • Nepotrebno, saj imamo vrniNti! • Kaj pa, če kličemo • zap.vrniNto(-5) • >>> a = PosploseniFibonacci() • >>> a._tabela • [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946] • >>> a.vrniNto(-5) • 1597 • Zakaj? • Kaj pa: • zap.vrniNto(-50) • if n <= 20 : return self._tabela[n] • IndexError: list index out of range
Ali ne gre lepše? • Izjeme • Če se zgodi kaj "čudnega" • Indeks izven meja, deljenje z 0 • Odpiranje neobstoječe datoteke za branje • ... • Python vrže izjemo / napako • Izjeme lahko "lovimo", mečemo pa lahko tudi svoje!