[Python] Metodi decorati con classi

Marco Giusti marco.giusti a gmail.com
Lun 22 Apr 2013 10:27:07 CEST


On Mon, Apr 22, 2013 at 08:58:39AM +0200, Pietro Battiston wrote:
[...]
> e la poesia di un
> 
> class myDecoratorC(object):
>     def __init__(self, f):
>         print "inside myDecoratorC.__init__()"
>         self.f = f
> 
>     def __call__(self, *args):
>         print "self is", self
>         print "args are", args
>         print "inside myDecoratorC.__call__()"
>         self.f( *args )
> 
> 
> @myDecoratorC
> def aFunction(*args):
>     print "inside aFunction()"

è la prima volta che vedo una classe usata come decoratore, solitamente
viene utilizzato un altro modo per conservare lo stato in un decoratore.
In questo caso non c'è stato da conservare ma i due seguenti casi
dovrebbero essere equivalenti, dove il secondo è quello più usato.


	class Knights:
		def __init__(self, say):
			self.say = "Nih"
		def __call__(self, func):
			def wrapper(*args, **kwds):
				print "The Knights who say %s!" % self.say
				return func(*args, **kwds)
			return wrapper


	def knights_f(say):
		def wrapper(func):
			def inner(*args, **kwds):
				print "The Knights who say %s!" % say
				return func(*args, **kwds)
			return inner
		return wrapper

	@Knights
	def foo():
		pass

	@knights_f
	def bar():
		pass


> Il problema è: come faccio ad unire gli approcci, ovvero ad avere un
> metodo decorato da una classe? O meglio: farlo è facile, ma nel seguente
> codice riassuntivo:
> 
> 
> class myDecoratorC(object):
>     def __init__(self, f):
>         print "inside myDecoratorC.__init__()"
>         self.f = f
> 
>     def __call__(self, *args):
>         print "self is", self
>         print "args are", args
>         print "inside myDecoratorC.__call__()"
> 
> def myDecoratorF(func):
>     def _decorator(self, *args):
>         print "self is", self
>         print "args are", args
>         print "inside myDecoratorF()"
>         return func(self, *args)
>     return _decorator
> 
> 
> class Decorata:
>     @myDecoratorC
>     def aFunction(self):
>         print "inside aFunction()"
>     
>     @myDecoratorF
>     def anotherFunction(self):
>         print "inside anotherFunction()"
> 
> 
> a = Decorata()
> a.aFunction()
> a.anotherFunction()
> 
> 
> Il mio problema è semplicemente che i due
>     print "self is", self
> stampano due cose diverse.

normale perché sono due cose diverse: il primo argomento di un metodo è
sempre l'istanza di classe, nel caso di myDecoratorC, in __call__, self
è un'istanza di myDecoratorC. Quello che induce in errore è che non
vengono passati argomenti a __call__, il problema è come python
gestisce i metodi. myDecoratorC non è una "user-defined function" e
quindi non viene creato un oggetto metodo che accetta l'istanza della
classe Decorata. 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à?

ciao
m.


Maggiori informazioni sulla lista Python