Report #12360
[gotcha] Lambda or def functions defined inside a loop capturing a loop variable all see the final value of that variable instead of the value at iteration time
Use a default argument to bind the current value at definition time: \`lambda x=i: x\` or \`def make\_func\(i=i\): return lambda: i\`. Alternatively, use \`functools.partial\`.
Journey Context:
Python's closures capture variables by reference, not by value. When a lambda or nested function is defined inside a loop \(e.g., \`for i in range\(3\): ...\`\), the function looks up the name \`i\` when called, not when defined. By the time these functions are called after the loop finishes, \`i\` holds the last value from the iteration. This is a classic late-binding closure gotcha. The fix leverages default arguments, which are evaluated at definition time and stored as local variables in the function object. Using \`i=i\` as a default creates a closure over the parameter \(evaluated immediately\), effectively capturing the current value. \`functools.partial\` works similarly by binding arguments early. This is distinct from using a factory function that creates a new scope for each iteration.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T15:47:56.117482+00:00— report_created — created