Python Functions
Python Closures
A closure is a nested function that remembers and can use variables from its enclosing function's scope, even after that outer function has finished running. Closures are a neat way to carry state around.
What Makes a Closure
A closure happens when three conditions are true: there is a nested function, the inner function references a variable defined in the outer (enclosing) function, and the outer function returns that inner function. The inner function then "closes over" the variable it needs, carrying it along.
def make_multiplier(factor):
def multiply(number):
return number * factor # factor comes from the enclosing scope
return multiply
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15Even though make_multiplier() has already finished running, double() still remembers factor=2 — that captured state is exactly what a closure is.
Closures That Keep Changing State
Combined with the nonlocal keyword, a closure can maintain and update its own private state across multiple calls — a lightweight alternative to a full class for simple cases.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
count_visits = make_counter()
print(count_visits()) # 1
print(count_visits()) # 2
print(count_visits()) # 3Why and When to Use Closures
Closures are handy for building "function factories" that generate specialised functions on the fly, for keeping small pieces of private state without a class, and they are the exact mechanism that makes Python decorators possible under the hood.
- Function factories — generate customised functions like make_multiplier above.
- Data hiding — keep a variable private inside a closure instead of exposing it globally.
- Decorators — nearly every Python decorator is built using a closure.
- Callbacks — pass around a function that still remembers useful context.
You can inspect what a closure has captured using function_name.__closure__ — useful for understanding how it works, though rarely needed in everyday code.
