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

Reply via email to