【发布时间】:2017-04-06 01:47:18
【问题描述】:
我正在 python 中实现一个观察者可观察的模式:
这是 Observable 类:
class Observable(object):
def __init__(self, value):
self.value = value
self.observers = []
def set(self, value):
old = self.value
self.value = value
self.notifyObservers(old, self.value)
def get(self):
return self.value
def addObserver(self, o):
self.observers.append(o)
def removeObserver(self, o):
if o in self.observers:
self.observers.remove(o)
def notifyObservers(self, old, new):
for o in self.observers:
o.valueChanged(old, new)
这是一个观察者:
class Observer(object):
def __init__(self, foo):
self.foo = foo
self.foo.addObserver(self)
def __del__(self):
print('Observer.__del__ called')
self.foo.removeObserver(self)
def valueChanged(self, old, new):
print('foo changed from %s to %s' % (old, new))
代码按预期工作。
但我需要销毁 Observer(即,当它未被引用时,它应该将自己从 Observable 对象的观察者列表中删除)。
问题在于,使用此代码,如果 Observer 在某些 Observable 对象的观察者列表中,则永远不会调用 Observer.__del__。
请注意,我不一定要显式销毁Observer,它也会因为变量赋值而未被引用,因此在销毁之前显式调用removeObserver() 不可行。
如果我注释掉self.foo.addObserver(self),那么就没有对Observer 的额外引用,并且在其上调用del 将调用Observer.__del__。
这个场景的测试用例是:
foo = Observable(23)
bar = Observer(foo)
foo.set(44)
bar = None
foo.set(1)
它有两个结果:
- 如果
self.foo.addObserver(self)没有被注释掉,它会打印出foo changed from 23 to 44和foo changed from 44 to 1 - 如果
self.foo.addObserver(self)被注释掉,它会打印Observer.__del__ called
【问题讨论】:
-
你看过weakrefs吗?弱引用旨在解决这个问题,并且自 2.4 以来一直是 Python 的一个特性。
标签: python observer-pattern reference-cycle