Násobky a delitele s dekorátorom
Mechanizmus dekorátorov
V projekte násobky a delitele sme porušili zásadu neduplikovania kódu. Vo views.py sa opakovala kontrola parametra cislo.
Potrebujeme nejako vytiahnuť spoločný kód von z views.
Toto je možné vyriešiť niekoľkými spôsobmi, jeden elegantný je tu.
Využijeme to, že funkcia v pythone je objekt ako každý iný.
Pozrite sa na tento kód:
1 def skontroluj_cislo(f):
2
3 # * __dekorovane_f je funkcia s dvomi premennymi
4 # ocakava, ze v nadradenom prostredi je nastavena premenna f
5
6 def __dekorovane_f(request,cislo):
7
8 # cislo je retazec
9 # musime ho previest na int
10 # treba kontrolovat vstup uzivatela!
11 try:
12 cislo_int=int(cislo)
13 except ValueError:
14 return chyba("%s sa nepodarilo previest na cislo" % cislo)
15 if cislo_int<0:
16 return chyba("cislo %d je zaporne" % cislo_int)
17 return f(request,cislo_int)
18
19 return __dekorovane_f
skontroluj_cislo je funkcia druhého rádu -- ako parameter dostáva funkciu dvoch premenných a vracia funkciu dvoch premenných. Vrátená funkcia robí to isté ako pôvodná, ale predtým skontroluje druhý parameter, a ak je chybný, vráti chybu.
Teraz môžeme zmeniť funkciu nasobky takto:
1 # * Toto je povodna funkcia nasobky, z ktorej sme vyhodili
2 # kontrolu cisla
3 # * Ako parameter ocakava uz cislo, nie retazec
4 def nasobky(request,cislo_int):
5
6 zoz_nasobkov=[]
7 for i in range(11):
8 zoz_nasobkov.append(Dvojica(i,i*cislo_int))
9 c=Context({'cislo':cislo_int,'vysledky':zoz_nasobkov})
10 t=loader.get_template("nasobky.html")
11 return HttpResponse(t.render(c))
12
13 # * Blizime sa k pointe:
14 # * Nasledujuci riadok obohati funkciu nasobky
15 # o kontrolu parametra cislo.
16 nasobky=skontroluj_cislo(nasobky)
A podobne upravíme funkciu delitele.
Celý projekt je tu: nasobky_a_delitele_v2.tar.gz.
Špeciálna syntax pre dekorátory
Horeuvedený vzor považovali autori Pythonu za dostatočne dôležitý na to, aby mu vyhradili špeciálnu syntax. Nasledujúci kód v má v zásade rovnakú funkciu ako predošlý, líši sa iba syntaxou. Všimnite si, že špeciálna syntax sa nachádza pred funkciou, takže ju čitateľ kódu neprehliadne.
1 # Teraz pouzijeme specialnu syntax, ktora zabezpeci
2 # obalenie funkcie dekoratorom
3 @skontroluj_cislo
4 def nasobky(request,cislo_int):
5
6 zoz_nasobkov=[]
7 for i in range(11):
8 zoz_nasobkov.append(Dvojica(i,i*cislo_int))
9 c=Context({'cislo':cislo_int,'vysledky':zoz_nasobkov})
10 t=loader.get_template("nasobky.html")
11 return HttpResponse(t.render(c))
Verzia so špeciálnou syntaxou je tu :nasobky_a_delitele_v2.1.tar.gz
Viac o dekorátoroch
Horeuvedený text vysvetľuje iba podstatu veci, ak sa chcete dozvedieť o dekorátoroch v Pythone viac, googlite.
Django poskytuje niekoľko dekorátorov, ktoré slúžia na dekoráciu views a (typicky) kontrolujú request, či spĺňa nejakú predbežnú podmienku predtým, ako vykonajú normálny kód view. Napríklad login_required a podobne.