[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