How do lexical closures work?
Python is actually behaving as defined. Three separate functions are created, but they each have the closure of the environment they're defined in - in this case, the global environment (or the outer function's environment if the loop is placed inside another function). This is exactly the problem, though - in this environment, i is mutated, and the closures all refer to the same i.
Here is the best solution I can come up with - create a function creater and invoke that instead. This will force different environments for each of the functions created, with a different i in each one.
flist = []for i in xrange(3): def funcC(j): def func(x): return x * j return func flist.append(funcC(i))for f in flist: print f(2)
This is what happens when you mix side effects and functional programming.
The functions defined in the loop keep accessing the same variable i
while its value changes. At the end of the loop, all the functions point to the same variable, which is holding the last value in the loop: the effect is what reported in the example.
In order to evaluate i
and use its value, a common pattern is to set it as a parameter default: parameter defaults are evaluated when the def
statement is executed, and thus the value of the loop variable is frozen.
The following works as expected:
flist = []for i in xrange(3): def func(x, i=i): # the *value* of i is copied in func() environment return x * i flist.append(func)for f in flist: print f(2)
Here's how you do it using the functools
library (which I'm not sure was available at the time the question was posed).
from functools import partialflist = []def func(i, x): return x * ifor i in xrange(3): flist.append(partial(func, i))for f in flist: print f(2)
Outputs 0 2 4, as expected.