Python Closures
A closure is a function that remembers variables from the scope where it was created. The remembered variables can outlive the outer function call.
Read an outer variable
Define the inner function inside the outer one. It reads the outer variable like its own.
def outer():
message = "from outside"
def inner():
print(message)
inner()
outer()Return a configured function
A factory is a function that builds a new function. The setting is remembered by the new function.
def make_multiplier(factor):
def multiply(number):
return number * factor
return multiply
double = make_multiplier(2)
print(double(7))Change the remembered value
Reading needs no special word. Changing an enclosing variable needs nonlocal.
def make_counter():
count = 0
def step():
nonlocal count
count += 1
return count
return stepEach closure keeps its own values
Two calls to the factory make two counters. Each counter remembers a separate count.
first = make_counter()
second = make_counter()
print(first(), first())
print(second())Example
def make_multiplier(factor):
def multiply(number):
return number * factor
return multiply
def make_counter():
count = 0
def step():
nonlocal count
count += 1
return count
return step
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5))
print(triple(5))
counter = make_counter()
print(counter())
print(counter())
print(counter())Key points
- Closure: a function that remembers variables from the scope where it was created
- Factory: a function that returns a new function with settings baked in
- Use nonlocal to change a variable from the nearest enclosing function scope
- LEGB order: Local, then Enclosing, then Global, then Built-in
- Each factory call creates a separate set of remembered variables
In this example, make_multiplier is called with 2 and with 3. Each call returns a multiply function. Each returned function remembers its own factor. Next, make_counter creates a count that starts at 0. The step function uses nonlocal to change that count. Each step call adds 1 and returns the new count. The final prints show 1, then 2, then 3.
Note
nonlocal never reaches the global scope.
Use global when you need that scope.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
What does the nonlocal keyword let an inner function do?