Decorating methods - where do my arguments go?

MRAB google at mrabarnett.plus.com
Fri May 8 12:27:36 EDT 2009


Mikael Olofsson wrote:
> Hi all!
> 
> I have long tried to avoid decorators, but now I find myself in a 
> situation where I think they can help. I seem to be able to decorate 
> functions, but I fail miserably when trying to decorate methods. The 
> information I have been able to find on-line focuses on decorating 
> functions, and do not mention any special problem regarding methods.
> 
> Consider the following example. I start by defining a simple decorator:
> 
>  >>> class test_decorator(object):
> ...     def __init__(self,func):
> ...         self._func = func
> ...     def __call__(self, *args):
> ...         print 'Decorator:', args
> ...         self._func(*args)
> 
> Then I decorate a function:
> 
>  >>> @test_decorator
> ... def func(*args):
> ...     print 'Function: ', args
> 
> Let's try that:
> 
>  >>> func(1,2,3)
> Decorator: (1, 2, 3)
> Function:  (1, 2, 3)
> 
> OK! That was what I expected. Let's decorate a method:
> 
>  >>> class cls(object):
> ...     @test_decorator
> ...     def meth(self,*args):
> ...         print 'Method:   ', args
> 
> Then try that:
> 
>  >>> cls().meth(1,2,3)
> Decorator: (1, 2, 3)
> Method:    (2, 3)
> 
> Oops! That's weird. I had expected - or at least wanted - the same 
> result as for the function above.
> 
> Where did the first argument go? If it was sent to the original method 
> meth as the real first argument (self), then why did I not get an 
> exception?
> 
> More importantly: How do I write a decorator that does not drop arguments?
> 
> I guess it all has to do with the fact that the returned callable isn't 
> a method of cls. Is it possible to write a decorator that returns a 
> callable that is a method of cls, when used on methods in cls?
> 
 >>> class cls(object):
     @test_decorator
     def meth(self,*args):
         print 'self:     ', self
         print 'Method:   ', args

 >>> cls().meth(1,2,3)
Decorator: (1, 2, 3)
self:      1
Method:    (2, 3)



More information about the Python-list mailing list