Python dekoraterji


Moji prvi koraki k razumevanju dekoraterjev v Pythonu. Sliši se kot ena čarovnija, a na koncu izpade, da bi znalo biti uporabno. 🙂 Kar dejansko je, saj jih uporabljam pri razvoju spletnih strani v Flasku.

Dekoraterji v Pythonu so funkcije ali razredi, ki spremenijo funkcijo, k kateri jim pripnemo. Uporabni so predvsem takrat, ko želimo validirati argumente funkcije, ki jo dekoriramo ali jih spremeniti, storiti nekaj pred to funkcijo (npr. vzpostavitev povezave) ali po njej (npr. zapiranje povezav), se odločiti, ali bomo izvedli funkcijo na podlagi argumentov ali ne ter spremeniti izhod funkcije. Dekoraterji nenazadnje tudi izboljšujejo berljivost izvorne kode (kar je tudi ena od filozofij pythona).

Dekoraterje se pripne funkciji tako, da se nad glavo funkcije napiše “@” in ime dekoraterja. Dekorater je funkcija ali razred, ki sprejme funkcijo, ki jo dekorira, kot argument in pokliče funkcijo, v kateri se izvede procedura, s katero dekoriramo funkcija.

Prvi primer je prepost: rezultat funkcije ovijemo v značke, ki nam v HTML-ju odebeljijo tekst.

[python]
#!/usr/bin/env python
# coding: utf-8

def bold(fn):
def bold_fn():
return "<b>" + fn() + "<b>"
return bold_fn

@bold
def hello():
return "hello world"

# izpiše <b>hello world</b>
print hello()
[/python]

Drugi primer je malo bolj zahtevnejši: funkcijo izvedemo le, če seznam vsebuje le števila tipa int ali float (argument funkcije pred izvedbo torej validiramo).

[python]
#!/usr/bin/env python
# coding: utf-8

def numbers_only(fn):
def wrapped(args):
numbers = [isinstance(x, (int, float)) for x in args]
if all(numbers):
return fn(args)
else:
return
return wrapped

@numbers_only
def squared(l):
return map(lambda x: x**2, l)

# seznam s samimi števili. Izpiše nov seznam.
print "Rezulat 1:", squared([1, 2, 3, 4, 5, 6])

# seznam z enim elementom, ki ni število. Izpiše None
print "Rezultat 2:", squared([1,2,3,4, "2"])
[/python]