[Python] Re: Digest di Python, Volume 19, Numero 11
Daniele Varrazzo
piro a develer.com
Ven 16 Nov 2007 14:50:24 CET
Pietro Battiston ha scritto:
> Nella documentazione ufficiale
> (http://docs.python.org/ref/customization.html), sta scritto " If
> __new__() returns an instance of cls, then the new instance's __init__()
> method will be invoked"
> In un'altra pagina sull'argomento
> (http://www.wellho.net/mouth/1146_-new-v-init-python-constructor-alternatives-.html),
> invece ho trovato scritto "If __new__ is defined on a class, it is
> called in preference to __init__"
>
> Ma il seguente codice non mi conferma né l'una né l'altra ipotesi!
>
> #####################
> import Tkinter
>
> class finestra(Tkinter.Toplevel):
> def __new__(cls):
> print "uno"
> return Tkinter.Tk()
> def __init__(self):
> print "due"
> root=finestra()
> #####################
Io credo che __new__ sia utilizzabile solo sulle new-style classes (quelle che
erediti da object). Poiché tu erediti da cose altrui (Tkinter.Toplevel) non
hai il controllo dell'ancestore:
In [5]: issubclass(Tkinter.Toplevel, object)
Out[5]: False
Non ho seguito bene quello che vuoi fare, anche perché non conosco bene le Tk.
Ma quando cominci a richiedere troppe magie ad un costruttore, forse ti
conviene usare una funzione "factory" che ti costruisca un oggetto e che te lo
modifichi secondo i tuoi requisiti prima di restituirlo al chiamante.
In Python si possono fare anche altre cose semimagiche, tipo iniettare un
metodo in una classe per ritrovarselo in tutte le sottoclassi e istanze... ma
io preferisco non usare troppe magie (diciamo che tendo a non fare cose che
non sarei in grado di rifare in altri linguaggi di programmazione) che magari
dipendono da dettagli implementativi (es. cose che funzionano solo quando una
classe ha un __dict__ e che poi si rompono se applicate a estensioni C).
Se mi spieghi a parola cosa devi fare proviamo a cercare il modo meno oscuro
possibile di farlo. Ma ecco una traccia:
class Window:
"""Una classe senza magie, magari fatta da qualcun altro."""
def __init__(self, n):
self.n = n
def render(self):
print self.n
# ma tu vuoi una classe che abbia in piu' un metodo "update"
# e anche un attributo "string"
def update(self, n):
"""Il metodo da aggiungere"""
self.n = n
def window_factory(n):
"""Funzione che costruisce Window "attrezzate"."""
w = Window(n)
w.update = lambda n: update(w, n) # nuovo metodo sull'istanza
w.string = 'ciao' # nuovo attributo sull'istanza
return w
myw = window_factory(10)
myw.render() # stampa 10
myw.update(20)
myw.render() # stampa 20
print myw.string # stampa 'ciao'
--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
Maggiori informazioni sulla lista
Python