Decorating methods - where do my arguments go?

Mikael Olofsson mikael at isy.liu.se
Fri May 8 17:33:34 CEST 2009


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?

/MiO



More information about the Python-list mailing list