gary jefferson wrote:
I don't quite understand the behavior of lambdas in the following code:
values = [(1, 'one'), (2, 'two'), (3, 'three')] for i, v in values: deferred = someDeferred(i) deferred.addCallback(onething, i, lambda: twothing(v)) dlist.append(deferred) dl = defer.DeferredList(dlist) dl.addCallback(done)
Which produces: onething: 1, result 1 twothing: three onething: 2, result 2 twothing: three onething: 3, result 3 twothing: three all done
Why does the call to twothing() (via a lambda and callableThing) always bind to 'three'? How do I change the code to get it to bind successively to 'one', 'two', and 'three'?
You don't need Twisted to see this:
>>> values = ['one', 'two', 'three'] >>> functions =  >>> for value in values: ... functions.append(lambda: value) ... >>> for func in functions: print func() ... three three three
The simplest fix is use "lambda foo=foo: ...", to bind the value of the variable as it was at the time the lambda statement is executed to a local variable in that function. i.e.:
>>> values = ['one', 'two', 'three'] >>> functions =  >>> for value in values: ... functions.append(lambda v=value: v) ... >>> for func in functions: print func() ... one two three
Refer to the Python documentation about scoping for more details.