[Python] Metodi decorati con classi
Marco Giusti
marco.giusti a gmail.com
Lun 22 Apr 2013 15:40:41 CEST
On Mon, Apr 22, 2013 at 02:52:34PM +0200, Pietro Battiston wrote:
> Il giorno lun, 22/04/2013 alle 13.53 +0200, Pietro Battiston ha scritto:
> > Il giorno lun, 22/04/2013 alle 10.27 +0200, Marco Giusti ha scritto:
> > > On Mon, Apr 22, 2013 at 08:58:39AM +0200, Pietro Battiston wrote:
> > > [...]
> > > >[...]
> > > >
> > > > Il mio problema è semplicemente che i due
> > > > print "self is", self
> > > > stampano due cose diverse.
> > >
> > > normale perché sono due cose diverse: [...]. Forse è per questo che non si vede spesso oggetti usati
> > > come decoratori.
> > >
> > > A questo punto mi chiedo l'utilità di avere una classe come decoratore.
> > > Incapsulazione? Ereditarietà?
> >
> >
> > [...]
> >
> > Alla luce del tuo chiarimento però mi è chiaro che questo modo di
> > operare è _meno_ potente...
>
> Ritratto:
> http://www.outofwhatbox.com/blog/2010/07/python-decorating-with-class/
>
> Sostanzialmente la soluzione è aggiungere alla classe decoratore il
> metodo
>
> def __get__(self, obj, ownerClass=None):
> # Return a wrapper that binds self as a method of obj (!)
> return types.MethodType(self, obj)
>
> e aspettarsi in __call__ il "self" dell'altra classe come secondo
> argomento:
>
> def __call__(self, otherself, *args):
> print "self is", self
> print "otherself is", otherself
> print "args are", args
> print "inside myDecoratorC.__call__()"
>
>
> Ho provato. Funziona. Con calma finirò anche per capire perché...
forse ti complichi un po' la vita ma sicuramente la complicherai a chi
verrà dopo di te. un antico proverbio cinese dice: "non scrivere mai
codice che non vorresti mantenere quando scritto da altri".
il codice funziona, ed è corretto, perché stai definendo un tipo
descrittore, pratica quando hai una situazione del genere: `a.x`, di
fatto ottieni un `x.__get__(a)` e quindi considerando il decoratore:
class Dec(object):
def __init__(self, f):
self.f = f
def __get__(self, instance, owner=None):
return types.MethodType(self, obj)
def __call__(self, other_self, *args, **kwds):
pass
class Spam(object):
@Dec
def foo(self):
pass
Spam().foo()
dovrebbe diventare:
s = Spam() # nessun problema
func = s.foo # foo.__get__(s, type(s))
func() # che è Dec.__call__
ma i descrittori sono una cosa bruttina, imho, e con casi particolari:
owner può non essere passato e instance può essere None.
ciao
m.
Maggiori informazioni sulla lista
Python