I am experiencing some weird bug in a code using observables in list comprehensions. I built here the simplest MWE I could think of:
class DummyObservable:
def __init__(self, value):
self.value = value
self.subscribers = set()
def __repr__(self):
return f"Dummy (id={id(self)}, value={self.value}, cbs={len(self.subscribers)})"
def subscribe(self, callback):
self.subscribers.add(callback)
callback(self.value)
return lambda: self.subscribers.remove(callback)
def get(self):
return self.value
def update(self, value):
self.value = value
for callback in self.subscribers:
callback(value)
It seems to work fine (check the observable id):
a = DummyObservable("foo")
b = DummyObservable("bar")
u = a.subscribe(lambda x: print(f"{id(a)}: {x}"))
#[Out:] 140257126530832: foo
a.update("fonzie")
#[Out:] 140257126530832: fonzie
a,b
#[Out:] (Dummy (id=140257126530832, value=fonzie, cbs=1), Dummy (id=140257126528096, value=bar, cbs=0))
Now, trying to subscribe inside a list comprehension:
[s.subscribe(lambda x: print(f"{id(s)}: {x}")) for s in [a,b]]
#[Out:]
140257126530832: fonzie
140257126528096: bar
Seems ok, so far. The id of a
and b
are printed correctly, showing the subscription is ok.
But... is it really? Look, this strange behavior:
a.update("foobar")
#[Out:]
140257126530832: foobar
140257126528096: foobar
What is going on? The update on "a" is calling the callback of "b". See running MWE.