I implement an observable observable pattern in python:
This is the Observable class:
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)
and this is the observer:
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))
The code works as expected.
But I need the Observer
be destroyed (i.e. when it is not displayed, it must be removed from the list of observers in the Observable
object).
The problem is that with this code, Observer.__del__
never called if Observer
is on the observer list of some Observable
.
Note that I do not necessarily destroy Observer
explicitly, it will also be impossible due to the assignment of a variable, thereby calling removeObserver()
explicitly before destruction is not viable .
If I comment on self.foo.addObserver(self)
, then there are no additional references to Observer
, and calling del
on it will call Observer.__del__
.
Test file for this scenario:
foo = Observable(23) bar = Observer(foo) foo.set(44) bar = None foo.set(1)
It has two results:
- If
self.foo.addObserver(self)
not commented out, it prints foo changed from 23 to 44
and foo changed from 44 to 1
- If
self.foo.addObserver(self)
commented out, it prints Observer.__del__ called