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? > > /MiO
You have to turn your decorator into a descriptor by providing a __get__() method. A primitive example: class test_decorator(object): def __init__(self,func): self._func = func def __call__(self, *args): print 'Decorator:', args self._func(self.inst, *args) def __get__(self, inst, cls): self.inst = inst return self Read more about the details at http://users.rcn.com/python/download/Descriptor.htm Peter -- http://mail.python.org/mailman/listinfo/python-list