In Python, closures are by variable, not by value. So when you refer to x
in a function, it refers to the most recent value assigned to x
, not to the value of x
when the function was defined. This gets non-intuitive results like the one below:
adders = []
for x in range(10):
adders.append(lambda y: x+y)
You intend to make a list of functions that add x
to a value, where x
varies from 0...9, but instead they all add 9 because that's the value of x
at the end of the loop.
You can override this by using a default argument to bind the name to its value at the time of the function definition.
x = 1
f = lambda y, x=x: x + y # x inside f is now locked at 1
x = 2
y = 3
z = f(x + y)
In this example you're not even actually dealing with a closure: x
here is actually a global variable. In Python, a closure can be created only when a function is defined inside another function, and the top-level or module-global namespace is not a function. But the same principle applies: the global variable can obviously be changed after the function is defined, so if you want to "lock in" its value at the time of function definition, you use a default argument.