我實現了一個Python觀察者觀察到的模式:如何正確實現觀測站蟒蛇當觀察者[應]銷燬
這是可觀察類:
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
你看過弱點嗎?弱引用旨在解決這個問題,並且自2.4以來一直是Python的一個特性。 –