Back to results for “Scope”
Python › Functions & Scope

How does a closure capture variables from its enclosing scope, and what pitfall occurs when creating multiple closures inside a loop?

Advanced

Answer

A closure captures enclosing variables BY REFERENCE (not by value at creation time), meaning it sees whatever the variable's value is when the closure ACTUALLY RUNS — creating multiple closures in a loop that all reference the SAME loop variable means they all end up seeing its FINAL value, a classic and common bug.
functions = []
for i in range(3):
    functions.append(lambda: i)  # all three closures capture the SAME 'i' variable

print([f() for f in functions])  # [2, 2, 2] -- NOT [0, 1, 2] as might be expected!

# Fixed with a default argument, evaluated at DEFINITION time per-iteration:
functions_fixed = [lambda i=i: i for i in range(3)]
print([f() for f in functions_fixed])  # [0, 1, 2]
Real-world example Debugging a classic closure bug where multiple queued callbacks unexpectedly all report the SAME final loop value.

Common follow-ups: Why does adding a default argument (i=i) specifically fix this closure-capture bug?