[Python] override di __getattribute__ per avere getter e setter "automatici"
Daniele Varrazzo
piro a develer.com
Lun 30 Giu 2008 02:43:22 CEST
Francesco Stablum ha scritto:
> Le metaclassi sono molto interessanti, cosi' come tutto l'aspetto di
> introspezione del python e
> le magnifiche lambda. Ho come l'impressione che tutti questi elementi
> manderanno in pensione
> un sacco di design pattern descritti in letteratura.
Questo è abbastanza comune: quelli che sono "pattern" in linguaggi di
programmazione di più basso livello tendono a diventare elementi di base in
linguaggi di livello più alto. Per esempio l'Iteratore poteva essere
considerato un "pattern" in C (ovvero una best practice, non rafforzata dal
linguaggio in se, ma riconosciuta come la soluzione migliore per una certa
classe di problemi), ma già in C++ è diventato qualcosa di centrale nel design
dell'STL e in Python è praticamente l'unico modo di visitare una collezione -
il for come "contatore" non c'è nemmeno nel linguaggio.
Quelli attualmente conosciuti come pattern non sono però da mandare in
pensione, anzi: con un linguaggio espressivo come il Python diventano facili
da implementare e la loro barriera di introduzione si abbassa. Ma sono
elementi "architettonici" di un sistema informatico: prendi il pattern Facade:
ti può aiutare a disaccoppiare due aree di un programma, non ha niente a che
vedere con il linguaggio in cui è implementato. Probabilmente è più facile
farlo in Python che in C++... quindi non ci sono scuse per non farlo!
> per Marco:
> e' vero, avrei potuto anche utilizzare direttamente property() ma nel
> caso di un gran numero
> di variabili d'istanza diventa troppo ripetitivo ogni volta dover
> specificare che il getter/setter di "foobar"
> e' get_foobar/set_foobar.
Però pensa a questo: se hai davvero così tanti di questi oggetti da dover
trattare che vuoi farlo in maniera più automatica possibile... allora quale
sarà il comportamento di tutti? Non mi viene difficile pensare che, per la
maggior parte dei casi, sarà
def set_foo(self, foo):
self._foo = foo
def get_foo(self):
return self._foo
ma allora, a questo punto, perché non lasci che foo sia un normale attributo?
> A livello di quantita' di codice cerco le soluzioni piu' "riassuntive"
> possibili.
Non avere niente è la quantità minima di codice (ha anche altre interessanti
proprietà, per esempio è autoreplicante...)
Probabilmente hai letto papiri in altri linguaggi che ti hanno insegnato a
nascondere sempre lo stato e fornire sempre metodi di accesso. Ma il problema
in questi linguaggi è che passare da un attributo pubblico a un getter
richiede un refactoring a tappeto, perché in Java/C++ la sintassi è diversa
(devi passare da "foo.bar" a "foo.bar()", e da "foo.bar = x" a
"foo.setBar(x)"), quindi ti consigliano di partire direttamente da questa
sintassi.
In Python questo problema non esiste: puoi cominciare a creare oggetti con
attributi pubblici, che andranno bene per la stragrande maggioranza dei casi.
Per quei pochi casi in cui ti serve un getter o un setter un po' più fancy,
puoi nascondere l'attributo foo in un __foo privato e aggiungere una property
"foo" che richiama _get_foo() e _set_foo(): tutto il codice che utilizzava la
tua classe continua a funzionare indisturbato.
Insomma, ti sei accorto che in Python si possono fare in automatico molte cose
che in Java o in C++ andavano noiosamente fatte a mano... peccato che poi ci
si accorga anche che alcune di quelle cose non ha più neanche tanto senso farle!
A presto!
--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
Maggiori informazioni sulla lista
Python