Phi*_*hil 59 python python-decorators
这是Python 2.5,它也是GAE,并不重要.
我有以下代码.我正在使用dec_check类作为装饰器在bar中装饰foo()方法.
class dec_check(object):
def __init__(self, f):
self.func = f
def __call__(self):
print 'In dec_check.__init__()'
self.func()
class bar(object):
@dec_check
def foo(self):
print 'In bar.foo()'
b = bar()
b.foo()
Run Code Online (Sandbox Code Playgroud)
执行此操作时,我希望看到:
In dec_check.__init__()
In bar.foo()
Run Code Online (Sandbox Code Playgroud)
但我得到" TypeError: foo() takes exactly 1 argument (0 given)"作为.foo()一种对象方法,以自我为参数.我猜测问题是bar当我执行装饰器代码时,实例并不存在.
那么如何将一个实例传递bar给装饰器类呢?
Ale*_*lli 81
你需要让装饰成一个描述符 -无论是确保其(元)类有一个__get__方法,或者,方式简单,通过使用装饰功能,而不是装饰类(因为功能已经描述符).例如:
def dec_check(f):
def deco(self):
print 'In deco'
f(self)
return deco
class bar(object):
@dec_check
def foo(self):
print 'in bar.foo'
b = bar()
b.foo()
Run Code Online (Sandbox Code Playgroud)
这打印
In deco
in bar.foo
Run Code Online (Sandbox Code Playgroud)
如预期的.
Gor*_*ley 46
当函数足够时,Alex的答案就足够了.但是,当您需要一个类时,可以通过将以下方法添加到装饰器类来使其工作.
def __get__(self, obj, objtype):
"""Support instance methods."""
import functools
return functools.partial(self.__call__, obj)
Run Code Online (Sandbox Code Playgroud)
要理解这一点,您需要了解描述符协议.描述符协议是将事物绑定到实例的机制.它由__ get __,__ set __和__ delete __组成,当从实例字典中获取,设置或删除事物时调用它们.
在这种情况下,当从实例获取东西时,我们使用partial将其__ call __方法的第一个参数绑定到实例.在构造类时,这是为成员函数自动完成的,但对于像这样的合成成员函数,我们需要显式地完成它.
Tho*_*ner 12
如果你想将装饰器编写为一个类,你可以这样做:
from functools import update_wrapper, partial
class MyDecorator(object):
def __init__(self, func):
update_wrapper(self, func)
self.func = func
def __get__(self, obj, objtype):
"""Support instance methods."""
return partial(self.__call__, obj)
def __call__(self, obj, *args, **kwargs):
print('Logic here')
return self.func(obj, *args, **kwargs)
my_decorator = MyDecorator
class MyClass(object):
@my_decorator
def my_method(self):
pass
Run Code Online (Sandbox Code Playgroud)