[Twisted-Python] lambdas and DeferredList

Andrew Bennetts andrew-twisted at puzzling.org
Fri Aug 3 03:06:25 MDT 2007


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.

-Andrew.





More information about the Twisted-Python mailing list