[Python] override di __getattribute__ per avere getter e setter "automatici"
Daniele Varrazzo
piro a develer.com
Dom 29 Giu 2008 19:07:56 CEST
Francesco Stablum ha scritto:
> Un saluto a tutti,
> mi chiamo Francesco e sono nuovo della lista :-)
Ciao!
> Ho cominciato ad usare il python un paio di mesi fa per lavoro e lo
> trovo un linguaggio estremamente interessante e potente, soprattutto
> sul versante dell'introspezione.
>
> Vorrei condividere con voi del codice che ho scritto per creare setter
> e getter "automatici".
>
> potete visionarlo al seguente url:
> http://rafb.net/p/bQDQAF11.html
>
> l'obiettivo e' quello di creare un "sostituto" di "object" per
> estendere le sue funzionalita' e dare la possibilita'
> di definire variabili d'istanza con l'override degli operatori
> "assegnazione" e "lettura".
>
> Per raggiungere questo scopo ho ridefinito i metodi __getattribute__ e
> __setattr__
>
> l'obiettivo e' quello che un pezzo di codice come questo:
>
> obj.foobar = 42
>
> chiami il metodo "set_foobar(42)" definito dentro "obj"
>
> come vi sembra come idea e come design?
E' un classico:
http://www.python.org/download/releases/2.2.3/descrintro/#metaclass_examples
tra l'altro anche io appena cominciato col Python ho sentito la necessità
impellente di realizzare qualcosa del genere. Ho idea ci si passi tutti :)
Questo è un lavoro da metaclasse, non da clase di base, per almeno un paio di
motivi. Il primo è di efficienza: con una metaclasse il codice decisionale
viene spostato a compile time e non a runtime: nei tuoi oggetti il "getattr" -
una delle operazioni più frequenti del linguaggio, passa attraverso ben due try.
Il secondo è di design: l'albero di ereditarietà è più adatto per progettare
un modello di dominio, non tanto per cambiare il comportamento di base di un
oggetto (da questo punto di vista è fuorviante che esista un "object" come
classe di base per creare le "new style classes", ma questo è un tradeoff che
è stato necessario per garantire la convivenza di nuove e vecchie classi senza
aggiungere ulteriori elementi sintattici nel linguaggio: in Python 3.0 sparirà).
Al di là di questo... tipicamente non serve aggiungere tanta magia all'oggetto
fondamentale del linguaggio. A meno che magari questo non faccia parte di un
framework per cui ogni getattr/setattr fa tanta magia: credo che PEAK
(http://peak.telecommunity.com/) facesse qualcosa del genere. (Il Python
Enterprise Application Kit non è stato esattamente accolto a braccia aperte:
credo faccia parte della mentalità del Python tenere le cose semplici e senza
troppa magia).
> inoltre ho un problemino: non riesco ad accedere alla variabile
> "__foobar" all'interno del metodo __getattribute__
> avete qualche idea? (il problema e' segnato con un FIXME all'interno
> del codice all'url http://rafb.net/p/bQDQAF11.html )
Non puoi accedere a variabili "__private" se non dalla stessa classe: né
sottoclassi né sopraclassi possono farlo. Devi usare variabili "_protette",
con un solo underscore.
Divertiti! Io ho ancora codice sparso in giro da qualche cliente che usava
cose di questo genere. Forse anche paggio (tipo un recordset all'interno di un
wrapper di getter/setter)... ne sono uscito, ma è stato istruttivo ;)
--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
Maggiori informazioni sulla lista
Python