Getting a set of lambda functions

Scott David Daniels Scott.Daniels at Acm.Org
Sun May 25 19:02:06 EDT 2008


Denis Kasak wrote:
...
>>>> spam = []
>>>> for i in range(10):
> ...   spam.append(lambda: i)
>>>> spam[0]()
> 9
>>>> spam[1]()
> 9
> 
> Manually creating the lambdas and appending them to a list works as
> expected, naturally; I don't see a good reason why it wouldn't work
> with a loop. Am I missing something?

Yes, you are missing something: binding time.  your anonymous function
returns the value of "i" in the enclosing scope _at_the_time_of_
_the function's_execution_.  If you follow your previous example with
'del i' and then execute any of your spam functions, you'll get an
"NameError: global name 'i' is not defined".

There are a couple of ways to slve your problem:
(1) use default args to do the binding at the function definition time.
     for i in range(10):
         spam.append(lambda arg=i: arg)
The lambda expression is normally spelled "lambda i=i: i)", but if you
don't know the idiom, I find the "i=i" part confuses people.

(2) Use something like functools.partial. if you are simply binding
     different args to the "same" function:

     import functools

     def thefunction(x):
         return x * 2

     spam = [functools.partial(thefunction, i) for i in range(10)]

--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list