Note that there are some explanatory texts on larger screens.

plurals
  1. POwhy are my weakrefs dead in the water when they point to a method?
    primarykey
    data
    text
    <blockquote> <p><strong>Possible Duplicate:</strong><br> <a href="https://stackoverflow.com/questions/599430/why-doesnt-the-weakref-work-on-this-bound-method">Why doesn&#39;t the weakref work on this bound method?</a> </p> </blockquote> <p>I'm using weakrefs in an observer-pattern and noticed an interesting phenomenon. If I create an object and add one of it's methods as an observer of an Observable, the reference is dead almost instantly. Can anyone explain what is happening?</p> <p>I'm also interested in thoughts for why this might be a bad idea. I've decided not to use the weakrefs and just make sure to clean up after myself properly with Observable.removeobserver, but my curiosity is killing me here.</p> <p>Here's the code:</p> <pre><code>from weakref import ref class Observable: __observers = None def addobserver(self, observer): if not self.__observers: self.__observers = [] self.__observers.append(ref(observer)) print 'ADDING observer', ref(observer) def removeobserver(self, observer): self.__observers.remove(ref(observer)) def notify(self, event): for o in self.__observers: if o() is None: print 'observer was deleted (removing)', o self.__observers.remove(o) else: o()(event) class C(Observable): def set(self, val): self.notify(val) class bar(object): def __init__(self): self.c = C() self.c.addobserver(self.foo) print self.c._Observable__observers def foo(self, x): print 'callback', x #never reached b = bar() b.c.set(3) </code></pre> <p>and here's the output:</p> <pre><code>ADDING observer &lt;weakref at 0xaf1570; to 'instancemethod' at 0xa106c0 (foo)&gt; [&lt;weakref at 0xaf1570; dead&gt;] observer was deleted (removing) &lt;weakref at 0xaf1570; dead&gt; </code></pre> <p>the main thing to note is that the print statement after the call to addobserver shows that the weakref is already dead.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. CODo you realize that `__observers` is a class variable and thus shared across all instances of `Observable` (this includes subclasses)? Also, if you're using name mangling (imho you shouldn't, but that's a different topic), you shouldn't access the mangled names from outside. Specifically, you hardcode a class name and access something which you presumably try to keep private.
      singulars
      1. This table or related slice is empty.
    2. COAh, so I should get rid of the class var declaration and use `if "__observers" in self.__dict__` instead of the `if not self.__observers`. Right-o. Almost missed that. Also, I know the private var should be kept private, I was just printing it for demonstration purposes. This whole name-mangling thing is new to me though, so thanks for putting a name to it (no pun intended) so I could google it... I wasn't sure why __observers was getting renamed to _Observable__observers. I'll probably call it _observers instead.
      singulars
    3. COdelnan: it appears your comment about `__observers` being a class variable isn't entirely true. Initially it is, but when `addobserver` is called, `self.__observers = []` initializes the instance variable. The class variable is still accessible (and still `None`), but only reachable by `Observable._Observable__observers`.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload