Dekorátory funkcií

Ak máme naprogramované funkcie a chceme ich vylepšiť pridaním nejakej novej vlastnosti, môžeme prepísať pôvodnú funkciu alebo použiť dekorátor. Dekorovať znamená ozdobiť, takže budeme funkciu nejako ozdobovať novým kódom.

Vytvorenie dekorátora

Dekorátor je funkcia, ktorá má parameter funkciu a vracia novú (vylepšenú, dekorovanú) funkciu.

Príklad zápisu jednoduchého dekorátora, ktorý modifikuje funkcie bez parametra:

def nazov_dekoratora(povodna_funkcia):
   def novafunkcia():
     #prikazy
     povodna_funkcia()
     #prikazy
   return novafunkcia

Ak povodna_funkcia vracia hodnotu pomocou return, v definícii dekorátora to musíme zohladniť:

def nazov_dekoratora(povodna_funkcia):
   def novafunkcia():
     #prikazy
     return povodna_funkcia()
   return novafunkcia

Použitie dekorátora

Dekorátor sa používa tak, že nad názov funkcie napíšeme názov dekorátora so symbolom @:

@nazov_dekoratora
def f(parametre funkcie):
  #prikazy

Príklad 1

Vytvoríme jednoduchý dekorátor, ktorý funkcie bez parametra obohatí o výpis 's dekoratorom':

def dekorator(povodna_funkcia):
   def novafunkcia():
     povodna_funkcia()
     print 's dekoratorom'
   return novafunkcia

Definícia novej funkcie s dekorátorom:

@dekorator
def f():
  print 'funkcia'

Zavoláme funkciu f:

f()

Vypise:

>>funkcia
>>s dekoratorom

Príklad 2

Urobíme dekorátor, ktorý ak sa vyskytne chyba, odchytí ju a niečo vypíše. Zamedzíme tak chybovým hlaseniam interpretera. Urobíme dekorátor tak, aby pracoval s funkciami, ktoré majú ľubovoľné parametre.:

def osetrene_chyby(funkcia):
    def nova(*args,**kwargs):
        try:
            return funkcia(*args,**kwargs)
        except:
            print 'chyba'
    return nova

Definujme nejaku funkciu, v ktorej by sa vypísalo chybové hlásenie.:

@osetrene_chyby
def ff(nejaky_text):
    print nejaky_text
    print 1/0

ff('Python podporuje dekoratory!')

Vypíše:

>>Python podporuje dekoratory!
>>chyba

... --Radek, Wed, 16 Feb 2011 16:23:58 +0100 reply

Pokud dekorovaná fuknce vrací hodnotu v return, pak to v dekorátoru zohledníme:

def nazov_dekoratora(povodna_funkcia):
   def novafunkcia():
     #prikazy
     result = povodna_funkcia()
     #prikazy
     return result
   return novafunkcia

Cumil --Cumil, Fri, 26 Jun 2015 08:21:01 +0200 reply

Díky, konečně se mi podařilo pochopit, k čemu to vlastně slouží. Je to napsané jednoduše a pěkně srozumitelně.