[python] Dekorátor
Hynek Fabian
hynek.fabian na firma.seznam.cz
Pondělí Únor 21 15:01:43 CET 2011
Radek (Wednesday 16 of February 2011 15:23:07):
> nejdřív bych se uvedl, jsem takový opakovaný začátečník, k Pythonu
> jsem naposled přičichl možná před osmi lety a nic moc. Teď, asi tři
> měsíce zpátky jsem se k němu vrátil, protože si hraju s GAE/P. Přes
> všechny problémy se zkouším prokousávat, ikdyž python bolí,
Něco děláš špatně. Kde to bolí?
> Jen tím že chci aby měl dekorátor parametry, se tak radikálně změní
> kód dekorátoru.
> Potřeboval bych nějak po lopatě vědět, co se uvnitř děje, protože
> cítím že ty dekorátory budu určitě používat ještě mnohem divočeji.
Vtip je v tom že se ve skutečnosti kód nijak nemění. Intuitivní představa že
parametry v závorkách by měly být předány dekorátoru je jen optický klam.
Pokud mám dekorátor jménem "spam"
@spam
pak
@spam("dirt")
je ve skutečnosti:
@spam.__call__("dirt")
A skutečný dekorátor je výsledek tohoto výrazu. Proč tak složitě?
Chování dekorátorů je koupodivu logičtější když zapomeneš na triviální
jednoslovné dekorátory a zauvažuješ jak se interpret popere se složitějšími
výrazy. Představ si například dekorátor který je metodou objektu:
@hamClass.spam("dirt")
Interpret ve skutečnosti uvidí toto:
hamClass.__getAttr__("spam").__call__("dirt")
Tady už není tak lehké říci co je samotný výraz a co by "intutivně" měly být
parametry výsledného dekorátoru. Ještě lepší to je pokud mám funkci která
vrací dekorátor:
@ham("dirt").spam("dirt")
je vlastně
@ham.__call__("dirt").__call__("dirt")
Proč by prakticky stejný token jednou měl být klasické volání funkce a podruhé
dekorátor? A pokud vymyslíš nějaké složité pravidlo jak to do sebe poznat:
@ham()
je dekorátor bez parametrů nebo funkce bez parametrů která vrací dekorátor?
Ergo "naivní" pohled na parametry dekorátoru by fungoval pokud by dekorátory
byly omezeny jen na primitivní výrazy, což by byla škoda.
Python tedy považuje všechno za zavináčem za výraz který bude interpretován
CELÝ a dekorátor je výsledek tohoto výrazu, včetně volání funkcí. To má krásný
efekt že dekorátor je běžná funkce (tj. jakýkoliv objekt s metodou
__call__()).
Objekty s tímhle nemají nic společného, pouze jmenný prostor uzávěry nahrazují
jmenným prostorem instance (metoda __call__ třídy vrací instanci)
Osobně považuji použití objektů k dekoraci za nešťastné. Metoda "uzávěra v
uzávěře" sice vypadá zezačátku děsivě, ale je aspoň přímočará a dá se pochopit
co se děje uvnitř. Objekty jen nahradí jednu složitost jinou (kolik lidí chápe
nuance metod __call__, __new__ a __init__?).
Další informace o konferenci Python