You are on page 1of 44

Visoka škola za informacijske tehnologije

Programske metode i apstrakcije

4. Predavanje
Python – napredne OOP teme

Dušan Mišljenčević
Podsjetnici

• Evidentirajte prisutnost: Obvezno se potpišite!


• Konzultacije – termin prema dogovoru, online
• SCAD – svi potrebni materijali i linkovi

Programske metode i apstrakcije 2


Slijedeći labos (1/3)

• Priprema za slijedeće laboratorijske vježbe

Programske metode i apstrakcije 3


Slijedeći labos (2/3)

• Priprema za slijedeće laboratorijske vježbe

Programske metode i apstrakcije 4


Slijedeći labos (3/3)

• Priprema za slijedeće laboratorijske vježbe

Programske metode i apstrakcije 5


Izlazni test

• Navedite primjere (različite od primjera s predavanja)


kôda u kojma se pojavljuju IndexError i TypeError.
• Deklarirajte jedan svoj izuzetak (exception). Navedite
kôd (minimalno kôd deklariranja) za svoj izuzetak.
• Kako string ‘ABC' pretvoriti u ‘abc'? Navesti kôd.
• Opcionalno: Kako string ‘aBC' pretvoriti u ‘Abc'?
Navesti kôd.

Programske metode i apstrakcije 6


Izlazni test - rješenja

'''IndexError''' '''String to lower'''


primjerListe = [2,8,9,7] string1 = 'ABC'
print(primjerListe[4]) print (string1.lower())

'''ValueError''' '''String capitalize'''


a = '5' + 3 string2 = 'aBC'
print (string2.capitalize())

print (string1.swapcase())
'''Custom exception'''
print (string2.swapcase())
class MojException(Exception):
pass
def provjeraPoslovnogPravila():
try:
x = int(input('Unesi cijeli broj veći od 2'))
if x <=2:
raise MojException("Broj mora biti veći od 2")
except MojException as e:
print('Korisnička pogreška:',e)

provjeraPoslovnogPravila()

Programske metode i apstrakcije 7


Agenda

• Objekti i klase – detaljnije


• Statički članovi
• Jednakost objekata
• Hash metoda
• Brisanje objekata
• Kontekstni upravitelji

Programske metode i apstrakcije 8


Objekti i klase detaljnije (1/8)

• Klasa je tip objekta u Pythonu


• Klase kreiramo uporabom ključne riječi class
class Person():
pass

print (type(Person))

<class 'type’>

• Klasama se mogu kreirati instance (instancirati)


➢ p = Person()
➢ p je objekt, Person je klasa
➢ Tip objekta je klasa koja je korištena za kreiranje instance
p = Person()
print (type(p))

<class '__main__.Person'>

Programske metode i apstrakcije 9


Objekti i klase detaljnije (2/8)

• Built-in atributi klasa u Pythonu


➢ Built-in atributi klasa daju informacije o klasama
➢ Upotrebom točke (.) ih se dohvaća
➢ Built-in atributi klasa u Pythonu su

Programske metode i apstrakcije 10


Objekti i klase detaljnije (3/8)

• Primjeri atributa klasa


class Person():
'''Ovdje opisujemo što klasa radi'''
pass

print(Person.__dict__)
print(Person.__doc__)
print(Person.__name__)
print(Person.__module__)
print(Person.__bases__)

{'__module__': '__main__', '__doc__': 'Ovdje opisujemo što klasa radi', '__dict__': <attribute '__dict__' of
'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
Ovdje opisujemo što klasa radi
Person
__main__
(<class 'object'>,)

Programske metode i apstrakcije 11


Objekti i klase detaljnije (4/8)

• Built-in atributi instanci klasa u Pythonu


➢ Atributi klase su varijable definirane direktno u klasi i vide ih
svi objekti unutar klase
➢ Atributi instanci (properties) definirani samo za tu instancu
klase – npr. u konstruktoru

class Person():
pass

p = Person()
print (p.__class__)
print (type(p) is p.__class__)

<class '__main__.Person'>
True

Programske metode i apstrakcije 12


Objekti i klase detaljnije (5/8)

• Provjera da li je objekt instanca određene klase


class Person():
pass

p = Person()
print (isinstance(p, Person))
print (isinstance(p, str))

True
False

• Svaka klasa je type objekt


➢ Nasljeđuje sve od type
➢ type joj je bazna klasa
➢ Na vrhu hijerarhije je klasa object

Programske metode i apstrakcije 13


Objekti i klase detaljnije (6/8)

• Built-in i korisnički definirani atributi


class Person(): class Program():
pass language = 'Python'
version = '3.9'
print (Person.__name__)
print (Program.__name__)
print (Program.language)
print (Program.version)

Person Program
Python
3.9

• Pristup i promjena vrijednosti atributa klasa


Program.version = '3.10'
print (Program.version)

3.10

Programske metode i apstrakcije 14


Objekti i klase detaljnije (7/8)

• Možemo koristiti getattr i setattr metode


class Program():
language = 'Python'
version = '3.9'

print (getattr(Program, 'version'))


3.9

setattr(Program, 'version', '3.10')


print (Program.version)
3.10

• Kreiranje atributa u run-time modu


Program.x = 1000 setattr(Program, 'y', 150)
print(Program.x, getattr(Program, 'x')) print(Program.y, getattr(Program, 'y'))
1000 1000 150 150

Programske metode i apstrakcije 15


Objekti i klase detaljnije (8/8)

• Kako je spremljeno stanje klase?


• mappingproxy klasa u type objektu
{ '__module__': '__main__’,
'language': 'Python’,
'version': '3.9’,
'__dict__': <attribute '__dict__' of 'Program' objects>,
'__weakref__': <attribute '__weakref__' of 'Program' objects>,
'__doc__': None
}
• mappingproxy je read-only dictionary
print(Program.__dict__['language'])
Python
• Nije svaki atribut u mappingproxy (npr.__name__ nije)
• Brisanje atributa klase (del i delattr – del je malo efikasniji)
Program.x = 100 del Program.x
setattr(Program, 'y', 150) delattr(Program, 'y')

Programske metode i apstrakcije 16


Objekti i klase detaljnije (9/9)

• Atributi klase mogu biti bilo koji objekti pa tako i funkcije


class Program():
language = 'Python'
version = '3.9'

def pozdrav():
print ('Pozdravlja vas {Program.language}')

print (Program.__dict__)
{'__module__': '__main__', 'language': 'Python', 'version': '3.9', 'pozdrav': <function Program.pozdrav at
0x0000019C6162D820>, '__dict__': <attribute '__dict__' of 'Program' objects>, '__weakref__': <attribute '__weakref__' of
'Program' objects>, '__doc__': None}

print(Program.pozdrav, getattr(Program, 'pozdrav'))


Program.pozdrav()
getattr(Program, 'pozdrav')()
Program.__dict__['pozdrav']()
<function Program.pozdrav at 0x000002BDC7E8D820> <function Program.pozdrav at 0x000002BDC7E8D820>
Pozdravlja vas Python
Pozdravlja vas Python
Pozdravlja vas Python

Programske metode i apstrakcije 17


Kratki kviz (1/2)

• Kreirajte klasu Stan s atributom adresa tipa str


• Klasi Stan dinamički dodajte atribut kucni_broj
• Ispišite vrijednost rječnika mappingproxy za klasu Stan

Programske metode i apstrakcije 18


Kratki kviz (2/2)

• Kreirajte klasu Stan s atributom adresa tipa str


• Klasi Stan dinamički dodajte atribut kucni_broj
• Ispišite vrijednost rječnika mappingproxy za klasu Stan
class Stan():
adresa: str
#adresa = ''

setattr (Stan, 'kucni_broj', int)


#setattr (Stan, 'kucni_broj', '')
#setattr (Stan, 'kucni_broj', '33')

print(Stan.__dict__)

{'__module__': '__main__', '__annotations__': {'adresa': <class 'str'>}, '__dict__': <attribute '__dict__' of


'Stan' objects>, '__weakref__': <attribute '__weakref__' of 'Stan' objects>, '__doc__': None, 'kucni_broj':
<class 'int'>}

Programske metode i apstrakcije 19


Statički članovi (1/6)

• U većini jezika static klasa se ne može


instancirati i djeluje kao globalni objekt; static
klasu ne možemo inherit
• Python nema static klasu (static keyword),
ali ima mogućnost definiranja static i class
varijabli i metoda
• static metode se u Pythonu koriste kad ne
želimo promjene/override
• static metode ne mogu dohvaćati class
variable ili instance variable

Programske metode i apstrakcije 20


Statički članovi (2/6)

• Class methods (@classmethod)


➢ class metode prihvaćaju klasu kao implicitni argument i
opcionalno bilo koji drugi argument specificiran u definiciji
➢ class metode nemaju pristup objektima instance metode
➢ class metode uglavnom služe kao alternativni konstruktori
• Static method (@staticmethod)
➢ u static metodama niti instanca (self) niti klasa (cls) nisu
predani kao argumenti
➢ ne mogu dohvaćati niti klasu niti njezine objekte (varijable,
instance,..)
➢ static metode su korisne kad želimo u klasu dodati neki dio
koji joj logički pripada

Programske metode i apstrakcije 21


Statički članovi (3/6)

• Instance klase i statički članovi


class NekaKlasa():
broj = 1

nekaInstanca = NekaKlasa()
print (nekaInstanca.broj)
nekaInstanca.broj = 5
print (NekaKlasa.broj, nekaInstanca.broj)
1
15

class NekaKlasa():
broj = 1

NekaKlasa.broj += 1
nekaNovaInstanca = NekaKlasa()
print (NekaKlasa.broj, nekaNovaInstanca.broj)
nekaNovaInstanca.broj += 1
print (NekaKlasa.broj, nekaNovaInstanca.broj)
22
23

Programske metode i apstrakcije 22


Kratki kviz (1/2)

• Napišite primjer klase MojaKlasa sa statičkim atributom moj_atr tipa


str te mu dajte inicijalnu vrijednost ′abc′
• Kreirajte jednu instancu inst1 klase MojaKlasa
• Promijenite vrijednost kreiranog atributa preko naziva klase te preko
kreirane instance
• Objasnite razliku u dva pristupa u prethodnom slučaju

Programske metode i apstrakcije 23


Kratki kviz (2/2)

• Napišite primjer klase MojaKlasa sa statičkim atributom moj_atr tipa


str te mu dajte inicijalnu vrijednost ′abc′
• Kreirajte jednu instancu inst1 klase MojaKlasa
• Promijenite vrijednost kreiranog atributa preko naziva klase te preko
kreirane instance
• Objasnite razliku u dva pristupa u prethodnom slučaju

class MojaKlasa():
moj_atr = 'abc'

print (MojaKlasa.moj_atr)

inst1 = MojaKlasa()
MojaKlasa.moj_atr='123'
inst1.moj_atr = 'def'
print (MojaKlasa.moj_atr, inst1.moj_atr)

abc
123 def

Programske metode i apstrakcije 24


Statički članovi (4/6)

• Primjer uporabe statičkih članova klase


class BrojacInstanci():
brInstanci = 0

def __init__(self):
BrojacInstanci.brInstanci += 1

prvaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

drugaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

trecaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

prvaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

1
2
3
4

Programske metode i apstrakcije 25


Statički članovi (5/6)

• Statične metode klase


class BrojacInstanci(): #ovo je greška jer je metoda ponistiBrojac statička
brInstanci = 0 print (prvaInstanca.ponistiBrojac())
def __init__(self):
BrojacInstanci.brInstanci += 1
def ponistiBrojac():
BrojacInstanci.brInstanci = 0

prvaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

drugaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

trecaInstanca = BrojacInstanci()
print (BrojacInstanci.brInstanci)

prvaInstanca = BrojacInstanci() 1
print (BrojacInstanci.brInstanci) 2
3
BrojacInstanci.ponistiBrojac()
4
prvaInstanca = BrojacInstanci() 1
print (BrojacInstanci.brInstanci)

Programske metode i apstrakcije 26


Statički članovi (6/6)

• Uvođenje dekoratora @staticmethod


class BrojacInstanci():
brInstanci = 0
def __init__(self):
BrojacInstanci.brInstanci += 1
print ('{0}. primjerak'.format(BrojacInstanci.brInstanci))
@staticmethod
def ponistiBrojac():
BrojacInstanci.brInstanci = 0
print('{0}. primjerak'.format(BrojacInstanci.brInstanci))
def ponistiBrojacNestat(self):
self.ponistiBrojac()

prvaInstanca = BrojacInstanci()
prvaInstanca.ponistiBrojac()
drugaInstanca = BrojacInstanci()
drugaInstanca. ponistiBrojacNestat()

1. primjerak
0. primjerak
1. primjerak
0. primjerak

Programske metode i apstrakcije 27


Jednakost objekata (1/2)

• Jednakost po identitetu
class Test():
nekaVar = 0

prviTest = Test()
drugiTest = prviTest
print (prviTest == drugiTest)
True

• Jednak sadržaj ne znači jednakost objekta


class Test():
nekaVar = 0

class Test1():
nekaVar = 0

prviTest = Test()
drugiTest = Test1()
print (prviTest == drugiTest)
False

Programske metode i apstrakcije 28


Jednakost objekata (2/2)

• Ekvivalentnost objekta

class Ekvivalent():
def __init__(self, var):
self._var = var
def __eq__(self, NekaTestKlasa):
return(self._var == NekaTestKlasa._var)

prvaInstanca = Ekvivalent(5)
drudaInstanca = Ekvivalent(5)
print (prvaInstanca == drudaInstanca)

True

Programske metode i apstrakcije 29


Kratki kviz (1/2)

• Kreirajte klasu Student s atributom prosjek


• Neka su dva studenta ekvivalentna ako imaju jednak prosjek
• Napišite kod koji podržava navedenu funkcionalnost

Programske metode i apstrakcije 30


Kratki kviz (2/2)

• Kreirajte klasu Student s atributom prosjek


• Neka su dva studenta ekvivalentna ako imaju jednak prosjek
• Napišite kod koji podržava navedenu funkcionalnost

class Student():
def __init__(self, prosjek):
self.prosjek = prosjek
def __eq__(self, DrugiStudent):
return(self.prosjek == DrugiStudent.prosjek)

student1 = Student(4.5)
student2 = Student(4.5)
print (student1 == student2)

True

Programske metode i apstrakcije 31


Hash metoda (1/2)

• __hash__ metoda je u paru s metodom __eq__


bitna ako se objektima pripadnog tipa želimo koristiti
kao ključevima u asocijativnim kolekcijama (npr.
rječnici)
• šifra : ključ
• proizvodi = { 1000:″jabuke″,
1100:″kruške″, 1111:″lubenice″}
• nastavit ćemo i sljedeće termine s hash metode

Programske metode i apstrakcije 32


Hash metoda (2/2)

class Osoba():
def __init__(self, ime, prezime):
self.ime = ime
self.prezime = prezime
def __hash__(self):
return hash((self.ime, self.prezime))
def __eq__(self, DrugaOsoba):
return(self.ime == DrugaOsoba.ime and self.prezime == DrugaOsoba.prezime)

pp = Osoba('Pero', 'Perić')
kk = Osoba('Krešo', 'Krešić')
ss = Osoba(‘Stipe', 'Stipić')
mjestoRodjenja = {
pp: 'Zagreb',
kk: 'Rijeka',
ss: 'Split',
Osoba('Niko', 'Nikić'): 'Dubrovnik',
Osoba('Frane', 'Franić'): 'Šibenik'
}

print(mjestoRodjenja[pp])

Zagreb

Programske metode i apstrakcije 33


Brisanje objekata (1/3)

• Brisanje objekta je pod nadzorom sustava za


upravljanje memorijom
• garbage collector
• Kada ne postoji referenca na objekt, isti se
proglašava smećem i u jednom trenutku se
njegova memorija oslobađa
• Programer ima malo mogućnosti utjecaja

Programske metode i apstrakcije 34


Brisanje objekata (2/3)

• naredbom del programer može obrisati ime


pridruženo objektu, ali objekt i dalje zauzima
memoriju dok ga sustav za oslobađanje memorije ne
oslobodi
• __del__ se obično naziva destruktor

Programske metode i apstrakcije 35


Brisanje objekata (3/3)

class BrojanjeObjekata():
broj = 0
aktivnih = 0
def __init__(self):
BrojanjeObjekata.broj += 1 Kreiran je objekt broj 1
self.brObjekata = BrojanjeObjekata.broj
print ('Kreiran je objekt broj {0}'.format(self.brObjekata)) U memoriji je 1 objekata
BrojanjeObjekata.aktivnih += 1 Kreiran je objekt broj 2
print ('U memoriji je {0} objekata'.format(BrojanjeObjekata.aktivnih)) U memoriji je 2 objekata
def __del__(self): Kreiran je objekt broj 3
print ('Obrisan je objekat broj {} '.format(self.brObjekata)) U memoriji je 3 objekata
BrojanjeObjekata.aktivnih -= 1
Obrisan je objekat broj 1
print ('Preostalo je u memoriji {} objekata'.format(BrojanjeObjekata.aktivnih))
Preostalo je u memoriji 2 objekata
k1 = BrojanjeObjekata() Obrisan je objekat broj 2
k2 = BrojanjeObjekata() Preostalo je u memoriji 1 objekata
kk = k1 Obrisan je objekat broj 3
k3 = BrojanjeObjekata()
Preostalo je u memoriji 0 objekata

Programske metode i apstrakcije 36


Context Manager (1/5)

• U svim programskim jezicima koriste se resursa kao file ili database


• Ove resurse je teško osloboditi nakon upotrebe
• Ako nisu oslobođeni, dolazi do tzv resource leakage i na kraju memory
leakage
• Sve to uzrokuje usporavanje sistema i na kraju crash
• Zato je korisno imati mehanizme za automatski setup i oslobađanje tj.
kontrolu resursa
• U Pythonu to radi context manager koji brine o ispravnom korištenju
resursa
• Najčešći je oblik kao u primjeru datoteka:

with open("test.txt") as f:
data = f.read()

Programske metode i apstrakcije 37


Context Manager (2/5)

• Naredbom with se oko bloka naredbi kreira


kontekst (ovojnica) koja osigurava da se prije ulaska u
blok i nakon izlaska iz bloka izvedu metode
__enter__, odnosno __exit__ koje su
definirane u objektu koji kao rezultat vraća izraz
neposredno nakon ključne riječi with
• Taj objekt se naziva Context Manager (kontekstni
upravitelj) jer je zadužen za definicije metoda koje se
izvode prilikom ulaska, odnosno izlaska iz dotičnog
konteksta

Programske metode i apstrakcije 38


Context Manager (3/5)

• Osnovna ideja je da se postupak odvija automatski sa


završetkom naredbe with

• Metoda __exit__ će se izvesti pri izlasku iz bloka uvijek, čak


i ako je izlazak iznenadan, npr. uzrokom iznimke
• Ključna riječ as je alias za naziv context managera

Programske metode i apstrakcije 39


Context Manager (4/5)

• Primjer
class ContextUpravitelj():
def __init__(self):
print ('__init__()')
def __del__(self):
print ('__del__()')
def __enter__(self):
print ('__enter__()')
return self
def __exit__(self, type, value, traceback):
print ('__exit__()')
def IspisiNesto(self):
print ('Nešto')

with ContextUpravitelj() as cu:


cu.IspisiNesto()

__init__()
__enter__()
Nešto
__exit__()
__del__()

Programske metode i apstrakcije 40


Context Manager (5/5)

• Primjer
class MyContext():
def __init__(self):
self.obj = None
def __enter__(self):
print ('Ulazak u context... ')
self.obj = 'Return object'
return self.obj
def __exit__(self, exc_type, exc_value, exc_traceback):
print('Izlazak iz context... ')
if exc_type:
print (f'Greška: {exc_type}, {exc_value}')
return False

with MyContext() as obj: Ulazak u context...


raise ValueError Izlazak iz context...
Greška: <class 'ValueError'>,
Traceback (most recent call last):
File "C:\Dusko\VSITE\PythonTest\Lib\main.py", line 15, in
<module>
raise ValueError
ValueError

Programske metode i apstrakcije 41


Agenda – što smo naučili

• Objekti i klase – detaljnije


• Statički članovi
• Jednakost objekata
• Hash metoda
• Brisanje objekata
• Kontekstni upravitelji

Programske metode i apstrakcije 42


Izlazni test

• Pripremite papire za rješenja


➢Napišite današnji datum
➢Napišite svoje ime i prezime
• Napišite primjer klase DrugaKlasa sa statičkim
atributom static_atr tipa float te mu dajte
inicijalnu vrijednost 1.5
• Kreirajte jednu instancu klase DrugaKlasa
• Promijenite vrijednost kreiranog atributa static_atr
preko naziva klase te preko kreirane instance
• Objasnite razliku u dva pristupa u prethodnom
slučaju

Programske metode i apstrakcije 43


Kraj 4. predavanja

Hvala na pozornosti!

Programske metode i apstrakcije 44

You might also like