title: Python - lambdas, not weakrefs, not pointers, not sure what
body: <p>I have this hobbyist pubsub library I put together that uses extensive <code>weakref</code> but I recently noticed that lambdas appear to be very similar in their execution, save some differences which strike me as... counter-intuitive. (if only because I'm not sure what lambdas are actually doing)</p>
  
  <p>Take the following class as an example of an object that might want to pub-sub:</p>
  
  <pre><code>&gt;&gt;&gt; class A(object):
  ...     def __init__(self, x):
  ...             self.x = x
  ...     def foo(self):
  ...             self.x += 1
  ...     def bar(self):
  ...             return "my x is %d" % self.x
  ... 
  &gt;&gt;&gt; Stick = A(15)
  &gt;&gt;&gt; Stick.x
  15
  &gt;&gt;&gt; Stick.foo()
  &gt;&gt;&gt; Stick.bar()
  'my x is 16'
  </code></pre>
  
  <p>Without importing the <code>weakref</code> library and hacking away at a custom weak reference to bound methods, one could use <code>lambda</code> to do something similar.</p>
  
  <pre><code>this = lambda: Stick.foo
  that = lambda: Stick.bar
  </code></pre>
  
  <p>Using <code>sys.getrefcount</code> before and after <code>this</code> and <code>that</code> are created will showcase that there is no change to the reference count for either the main object or its bound methods.</p>
  
  <pre><code>&gt;&gt;&gt; sys.getrefcount(Stick)
  2
  &gt;&gt;&gt; sys.getrefcount(Stick.foo)
  1
  &gt;&gt;&gt; sys.getrefcount(Stick.bar)
  1
  </code></pre>
  
  <p>Furthermore, the 'not-weakrefs' can be placed in a container, again without altering the refcount for the object or its bound methods.</p>
  
  <pre><code>events = [this, that]
  </code></pre>
  
  <p>Finally the 'not-weakref' lambdas can be called with double-parentheses. Looks a little ugly, but so do some of the 'weak bound method' hacks out there (including my own), so this is passable IMHO.</p>
  
  <pre><code>&gt;&gt;&gt; for e in events:
  ...     e()()
  ... 
  'my x is 17'
  &gt;&gt;&gt; 
  </code></pre>
  
  <p>Seems okay -- until the main object is deleted.</p>
  
  <pre><code>&gt;&gt;&gt; del Stick
  &gt;&gt;&gt; for e in events:
  ...     e()()
  ... 
  Traceback (most recent call last):
    File "&lt;stdin&gt;", line 2, in &lt;module&gt;
    File "&lt;stdin&gt;", line 1, in &lt;lambda&gt;
  NameError: global name 'Stick' is not defined
  &gt;&gt;&gt; 
  </code></pre>
  
  <p>We could write around this with a try/except -- but that's almost not worth talking about, because by simply creating a new instance with the same name as previous, lo and behold the event 'points' at the newly created instance of the object!</p>
  
  <pre><code>&gt;&gt;&gt; Stick = A(777)
  &gt;&gt;&gt; for e in events:
  ...     e()()
  ... 
  'my x is 778'
  &gt;&gt;&gt;
  </code></pre>
  
  <p>Note that a new object doesn't also have its <code>foo</code> and <code>bar</code> methods called - so this really is 'pointed' right at the same-named instance of the object.</p>
  
  <pre><code>&gt;&gt;&gt; Dave = A(15) #sets Dave.x to 15
  &gt;&gt;&gt; for e in events:
  ...     e()()
  ... 
  'my x is 779'
  &gt;&gt;&gt; Dave.x
  15
  &gt;&gt;&gt; Dave.bar()
  'my x is 15'
  &gt;&gt;&gt; 
  </code></pre>
  
  <p>This is the first time I've seen an object that can be so easily "re-called" after being deleted, or for that matter even successfully referencing a variable that doesn't. It 'feels' awfully magical.</p>
  
  <p>The Python docs just liken lambdas to anonymous functions and don't really talk about the under-the-hood (that I can tell) -- so what exactly is going on when defining and using lambdas? </p>
  
  <p>Side-question; is this fair game for an approach to pubsubbing, then, or is the convenience and apparent ubiquity of weakrefs the whole reason we tend to see those instead? (as opposed to, say, <code>try/except</code>ing your way through lambdas that no longer return valid functions or bound methods)</p>