Peter Otten wrote:
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
Thanks! Works perfectly for methods, as far as I can see. That's
perfectly OK, since that is what I was asking for. What I failed to
include in my original post is that I intend to use the decorator for
functions as well. The above fails for functions on the second row of
__call__ with
AttributeError: 'test_decorator' object has no attribute 'inst'
It seems to me like __get__ is not called when decorating a function. I
guess there's no reasonable value for inst in that case. It might be the
function itself, but it doesn't make sense to call the function with
itself as its first argument, when it isn't supposed to be called that way.
George Sakkis decorator function solution seems to work equally well for
functions and methods. However, I prefer the cleaner encapsulation given
by a class. Based on those observations, I think I will use the
following approach:
>>> class test_decorator(object):
... _inst = None
... def __init__(self,func):
... self._func = func
... def __call__(self, *args):
... print 'Decorator:', args
... if self._inst is None:
... print 'We seem to be decorating a function.'
... self._func(*args)
... else:
... print 'We seem to be decorating a method.'
... self._func(self._inst,*args)
... def __get__(self, inst, cls):
... self._inst = inst
... return self
...
>>>
>>> @test_decorator
... def func(*args):
... print 'Function: ', args
...
>>>
>>> func(1,2,3)
Decorator: (1, 2, 3)
We seem to be decorating a function.
Function: (1, 2, 3)
>>>
>>> class cls(object):
... @test_decorator3
... def meth(self,*args):
... print 'Method: ', args
...
>>>
>>> cls().meth(1,2,3)
Decorator: (1, 2, 3)
We seem to be decorating a method.
Method: (1, 2, 3)
If there are any drawbacks with this approach that I fail to see, please
enlighten me.
/MiO
--
http://mail.python.org/mailman/listinfo/python-list