Decorating methods - where do my arguments go?
Duncan Booth
duncan.booth at invalid.invalid
Tue May 12 04:25:59 EDT 2009
Michele Simionato <michele.simionato at gmail.com> wrote:
> On May 12, 8:54 am, Mikael Olofsson <mik... at isy.liu.se> wrote:
>> Peter Otten wrote:
>> > I usually use decorator functions, but I think the following should
>> > wor
> k,
>> > too:
>>
>> > class deco(object):
>> > def __init__(self, func):
>> > self._func = func
>> > def __call__(self, *args):
>> > print "Decorator:", args
>> > self._func(*args)
>> > def __get__(self, *args):
>> > return deco(self._func.__get__(*args))
>>
>> This looks like a winner to me. It is elegant, works for functions as
>> well as for methods, and does not mess with the internals of the
>> decorator which avoids the problems that Duncan pointed out.
>
> Still it turns something which is a function into an object and you
> lose the
> docstring and the signature. pydoc will not be too happy with this
> approach.
Also it means every time the decorator is invoked 'self' references a
new instance of deco. I don't know why Mikael wants to use a class
rather than a function but if he wants to save state between calls this
isn't going to help.
Something like this may work, and preserves the function name, type and
docstring:
from functools import wraps
class Decorator(object):
def __init__(self, func):
self._func = func
def __new__(cls, func):
decorator = object.__new__(cls)
decorator.__init__(func)
@wraps(func)
def wrapper(*args, **kwds):
return decorator(*args, **kwds)
return wrapper
class deco(Decorator):
def __init__(self, func):
self.calls = 0
Decorator.__init__(self, func)
def __call__(self, *args):
self.calls += 1
print "Decorator:", args, "called", self.calls, "times"
return self._func(*args)
class C(object):
@deco
def meth(self, arg):
"""meth's docstring"""
print "meth %r %r" % (self, arg)
return arg+1
inst1 = C()
inst2 = C()
print repr(inst1.meth), inst1.meth.__doc__
print inst1.meth(5)
print inst1.meth(inst2.meth(3))
-------------------
Output:
<bound method C.meth of <__main__.C object at 0x00B45390>> meth's
docstring
Decorator: (<__main__.C object at 0x00B45390>, 5) called 1 times
meth <__main__.C object at 0x00B45390> 5
6
Decorator: (<__main__.C object at 0x00B453D0>, 3) called 2 times
meth <__main__.C object at 0x00B453D0> 3
Decorator: (<__main__.C object at 0x00B45390>, 4) called 3 times
meth <__main__.C object at 0x00B45390> 4
5
--
Duncan Booth http://kupuguy.blogspot.com
More information about the Python-list
mailing list