How do you create a list of similar functions in Python?
As a simple example, let's say we want to create an array of 10 elements like this:
a[0] = lambda x: x
a[1] = lambda x: x+1
a[2] = lambda x: x+2
...
a[9] = lambda x: x+9
Simple:
>>> a = []
>>> for i in range(0,10): a.append(lambda x: x+i)
...
...but wrong:
>>> a[0](1)
10
What happened here? In Python, that lambda x: x+i
uses the value that i
will have when the function is invoked.
This is the trick to get it right:
>>> a = []
>>> for i in range(0,10): a.append(lambda x, i=i: x + i)
...
>>> a[0](1)
1
What happens here is explained in the section "A Jedi Mind Trick" of the
Instant Python article: i=i
assigns as the default value of the parameter i
the current value of i
.
Strangely enough the same article has "A Note About Python 2.1 and Nested Scopes" which seems to imply that from Python 2.2 the scoping has changed to "work as it should". I don't understand: the examples above are run on Python 2.4.4.
Googling for keywords related to python closure scoping only yields various sorts of complicated PEPs and an even uglier list trick:
a lot of people might not know about the trick of using a list to box variables within a closure.
Now I know about the trick, but I wish I didn't need to know :-(