A closure is an inner function that “remembers” names from the enclosing function’s scope, even after the outer function has returned. Those names are stored in the closure’s environment, so each returned inner function can carry its own captured values. Closures are the basis for decorators and for function factories (functions that return other functions). This article shows how they work and when to use nonlocal.
What they are
When a function is defined inside another, the inner function can read (and, with nonlocal, update) variables from the outer scope. When the outer function returns the inner function, the inner function keeps a reference to that outer scope—that bundle of names is the closure. See Scope and namespace for how Python looks up names.
Simple example: capturing a value
def outer(x):
def inner(y):
return x + y # x comes from outer's scope
return inner
add_five = outer(5)
add_ten = outer(10)
print(add_five(3)) # 8
print(add_ten(3)) # 13
Each call to outer creates a new inner that captures that call’s x.
Function factory: multiplier
def multiplier(n):
def multiply(x):
return x * n
return multiply
double = multiplier(2)
triple = multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
Mutable state: counter with nonlocal
To change an outer variable from the inner function, declare it nonlocal. Otherwise assignment would create a new local variable instead of updating the outer one.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c1 = make_counter()
print(c1(), c1(), c1()) # 1 2 3
c2 = make_counter()
print(c2()) # 1 — separate closure, separate count
When closures are useful
- Decorators: the wrapper closes over the original function. See Decorators.
- Factories: functions that return configured functions (e.g. multipliers, comparators).
- State without classes: a closure can hold mutable state (e.g. counter) without defining a class.
Next steps: Core Concepts · Decorators · Scope and namespace · Functions