【发布时间】:2026-01-08 12:45:02
【问题描述】:
下面非常简化的代码中的观察者模式运行良好。我希望有一个装饰器@on_event 在 Observable 单例中进行注册。
在下面的 O2 类中,这不起作用。问题当然是在创建实例之前调用了装饰器on_event get,并且注册将是未绑定方法event。在某种程度上,我必须延迟注册,直到 O2 对象被初始化。也许不用说,但我想在 O2 中添加的只是装饰器,如下面的代码所示。
但肯定有办法解决这个问题吗?我用谷歌搜索但找不到任何东西,并尝试了几种方法。
class Observable(object):
_instance = None
@classmethod
def instance(cls):
if not cls._instance:
cls._instance = Observable()
return cls._instance
def __init__(self):
self.obs = []
def event(self, data):
for fn in self.obs:
fn(data)
def on_event(f):
def wrapper(*args):
return f(*args)
Observable.instance().obs.append(f)
return wrapper
class O(object):
def __init__(self, name):
self.name = name
Observable.instance().obs.append(self.event)
def event(self, data):
print self.name + " Event: " + data
class O2(object):
def __init__(self, name):
self.name = name
@on_event
def eventx(self, data):
print self.name + " Event: " + data
if __name__ == "__main__":
o1 = O("o1")
Observable.instance().event("E1")
o2 = O2("o2")
Observable.instance().event("E2")
【问题讨论】:
-
那么,当事件触发时,该方法应该调用什么instance?这就是这里的问题;如果有实例将方法绑定到,则只能注册绑定方法。你想在这里注册什么?只有一个
O2实例的方法,O2的所有实例,还有什么? -
@MartijnPieters 在示例中应该在 o2 实例上调用 - 所有 O2 实例。 (就像 O 一样)
-
你不能单独使用装饰器来做到这一点;您还需要在
O2上设置一个元类以挂钩实例创建,然后在每次创建实例时注册绑定方法。 -
虽然理论上装饰器也可以将
__new__或__init__方法插入到同一个类命名空间中,然后进行挂钩;但这会很快变得丑陋,不推荐。 -
(请参阅 How does the function that is called inside the class declaration? 了解这有多难看;该特定技巧甚至在 Python 3 中都行不通)。
标签: python python-2.7 decorator python-decorators