[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