装饰python类的方法,我如何将实例传递给装饰器?

这是python2.5, GAE也不重要。

我有以下代码,我正在装饰bar中的foo()方法,使用dec_check类作为装饰器。

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() 

执行这个时,我希望看到:

 In dec_check.__init__() In bar.foo() 

但是我得到了“ TypeError: foo() takes exactly 1 argument (0 given) ”作为.foo() ,作为一个对象的方法,把自己作为一个参数。 我猜测问题是,当我执行装饰器代码时, bar的实例并不存在。

那么如何将一个实例传递给装饰类呢?

你需要通过确保它的(meta)类有一个__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() 

这打印

 In deco in bar.foo 

如预期的。

当一个函数足够时,Alex的回答就足够了。 但是,当你需要一个类,你可以通过添加以下方法到装饰类。

 def __get__(self, obj, objtype): """Support instance methods.""" import functools return functools.partial(self.__call__, obj) 

为了理解这个,你需要了解描述符协议。 描述符协议是将事物绑定到实例的机制。 它由__ get __,__ set __和__ delete __组成,当事物从实例字典中被获取,设置或删除时被调用。 在这种情况下,当事件从实例中获得时,我们将它的第一个参数__调用__方法绑定到实例,使用partial。 这是在构造类时为成员函数自动完成的,但是对于像这样的合成成员函数,我们需要明确地做到这一点。

装饰器在Python中可能有点棘手。 这里有一个我曾经工作过的例子。 你可以从中推断出你正在做的事情。

Djangoauthentication和Ajax – 需要login的URL

如果你想写的装饰作为一个类,你可以做。

 from functools import update_wrapper, partial MyDecorator(object): def __init__(self, func): update_wrapper(self, func) self.func = func def __get__(self, obj, objtype): """Support instance methods.""" return functools.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