Dekoratori

17.8 Dekoratori

Dekorator možeš da zamisliš kao prečicu za primenu tzv wrapper funkcije. Wrapper funkcije su takve funkcije koje pozivaju neku drugu funkciju, a da pri tome one mogu da rade nešto svoje ili da ne rade ništa (tj, mogu da pripremaju „sirove“ podatke iz programa za format koji glavna funkcija očekuje i slično). U suštini dekoratori nam mogu biti korisni da  bi smo "wrap" funkciju pozivali konstantno - sa istim delom programa, iznova i iznova dokle god se ne obavi potrebna obrada. Na primer, kreirao sam dekorator koji se zove ponovo, kako bih ga mogao primeniti na bilo kojoj funkciji, koji mi služi da, ukoliko se pojavi neka greška u radu, Python ne prekine izvršavanje programa, već da pokuša ponovno da pokrene funkciju, i to najviše 5 puta, sa malom pauzom između svakog novog pokušaja da obavi zadatak. Ovo može biti korisno u nekim situacijama, kao što su pokušaji uspostavljanja komunikacije sa računarom koji je negde na mreži (intrnetu):
#!/usr/bin/env python3 

'''Skripta koja simulira pokušaj uspostavljanja komunikacije.''' 

from time import sleep 
from functools import wraps 
import logging 

logging.basicConfig() 
log = logging.getLogger("ponovo") 

def ponovo(f): 
    @wraps(f) 
    def wrapped_funkcija(*arg, **kvarg): 
        MAKS_POKUSAJ = 5 
        for pokusaj in range(1, MAKS_POKUSAJ + 1): 
            try: 
                return f(*arg, **kvarg) 
            except: 
                log.exception("Pokušaj %s/%s nije uspeo : %s", 
                pokusaj, 
                MAKS_POKUSAJ, 
                (arg, kvarg)) 
                sleep(10 * pokusaj) 
            log.critical("Svi %s pokušaji su propali : %s", 
            MAKS_POKUSAJ, 
            (arg, kvarg)) 
    return wrapped_funkcija 

brojac = 0 

@ponovo 
def sacuvaj_u_bazu(arg): 
    print("Piši u bazu podataka ili uspostavi netvork konekciju itd.") 
    print("Ovo će se automatski ponovo izvršavati, ukoliko dođe do neke greške.") 
    global brojac 
    brojac += 1 
    if brojac < 2: 
        raise ValueError(arg) 
    
if __name__ == '__main__': 
    sacuvaj_u_bazu("Neka loša vrednost")
Što nam daje sledeći izlaz:
./pokusaj.py 
Piši u bazu podataka ili uspostavi netvork konekciju itd. 
Ovo će se automatski ponovo izvršavati, ukoliko dođe do neke greške. 
ERROR:ponovo:Pokušaj 1/5 nije uspeo : (('Neka loša vrednost',), {}) 
Traceback (most recent call last): 
  File "./pokusaj.py", line 18, in wrapped_funkcija 
    return f(*arg, **kvarg) 
  File "./pokusaj.py", line 39, in sacuvaj_u_bazu 
    raise ValueError(arg) 
ValueError: Neka loša vrednost 
CRITICAL:ponovo:Svi 5 pokušaji su propali : (('Neka loša vrednost',), {}) 
Piši u bazu podataka ili uspostavi netvork konekciju itd. 
Ovo će se automatski ponovo izvršavati, ukoliko dođe do neke greške. 
Ovo je malo napredan primer, ne moraš da ga znaš, ali je bitno da ga razumeš. Kao što vidiš, glavna funkcija nam je sacuvaj_u_bazu(). Budući da sam ispred nje koristio dekorator koji poziva funkciju ponovo() ovaj program pokušava da 5 puta izvrši glavnu funkciju. Obrati pažnju da je dekorator celu glavnu funkciju prosledio kao argument funkciji ponovo(), tj dekorator je uradio ovu stvar: ponovo(sacuvaj_u_bazu()). Za više informacija kako se radi sa dekoratorima pročitaj sadržaj koji se nalazi na ovom mestu.

17.7 assert naredba Indeks 17.9 Razlike između
verzija

Primjedbe

Popularno ovog meseca

Gde pronaći novosti sa facebook stranica nakon velike promene koja ga je zadesila?

Dva načina da vratite svoj Windows 10 na fabričke vrednosti

Kako preuzeti video koji je neko postavio na facebook-u bez upotrebe dodatnih programa?

Više neće biti moguć besplatan prelazak na Windows 10

Prijateljski meč ŠK "Titel" - ŠK "Bukovac"

Tu je novi Qt creator 4.4.0!

Kako manipulisati Windows licencom pomoću slmgr komande?

Fake poet

Da li je poželjno biti anoniman na internetu (ili se predstavljati punim imenom i prezimenom)?

Organizacija foldera i fajlova u Linux fajl sistemu