装饰器方法不起作用,因为装饰器是在构造类时调用的,而不是在构造实例时调用的。当你说
class Foo(object): @some_decorator def bar(self, *args, **kwargs): # etc etc
然后
some_decorator在构造类Foo时将调用它,并将为它传递一个 未绑定 方法,而不是实例的绑定方法。这就是为什么
self没有通过。
另一方面,第二种方法可以工作,只要您仅在使用装饰器的每个类中创建 一个 对象, 并且 您比较聪明。如果您定义
listen如上,然后定义
class Foo(object): def __init__(self, *args, **kwargs): self.some_method = self.some_method # SEE BELOW FOR EXPLANATION # etc etc @listen def some_method(self, *args, **kwargs): # etc etc
然后,
listen.__get__当有人试图打电话将被称为
f.some_method直接一些
f......但你的计划的整点是,没有人的这样做!事件回调机制
listen直接调用实例,这是因为它被传递了,并且
listen实例正在调用它在创建时所释放的未绑定方法。
listen.__get__永远不会被调用,并且
_self永远不会正确设置参数…
除非
您
self.some_method像在上述
__init__方法中那样显式访问自己。然后
listen.__get__将在实例创建时被调用并
_self进行正确设置。
问题是(a)这是一个可怕的骇客,并且(b)如果您尝试创建两个实例,
Foo则第二个实例将覆盖第一个实例
_self,因为仍然只有一个
listen对象正在创建,并且该对象与类,而不是实例。如果您只使用一个
Foo实例,那很好,但是如果您必须让事件触发两个不同
Foo的,则只需要使用“旧样式”事件注册即可。
TL,DR版本:装饰方法装饰类的 未绑定 方法,而您希望事件管理器传递实例的 绑定 方法。



