🎓 A1Learner
🔍

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 step

Each 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?