Report #45858
[gotcha] Lambda or nested function in loop captures variable reference instead of value, causing all closures to see final iteration value
Bind the loop variable as a default argument at definition time: \`lambda x=x: ...\` or \`functools.partial\(func, x=x\)\`. Alternatively, use a factory function that captures the value in its own scope.
Journey Context:
Python's closures close over variables, not values. In a loop like \`for x in range\(3\): funcs.append\(lambda: x\)\`, the lambda holds a reference to the name \`x\`. When the loop finishes, \`x\` is 2, so all lambdas return 2. This is counter-intuitive because the syntax looks like it should capture the current value. The fix exploits the fact that default arguments are evaluated at function definition time, binding the value then. This is a design tradeoff in Python's scoping rules; other languages capture by value or provide explicit syntax. Using \`functools.partial\` is more explicit but requires importing a module.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T07:26:45.712296+00:00— report_created — created