Codectionary / Developer documentation / Python

nonlocal: update an enclosing binding

Keep small amounts of state in a closure without using a module-level variable.

How it works

nonlocal selects an existing binding in the nearest enclosing function scope. It is useful when a nested function must rebind state retained by its enclosing function.

It cannot create a new enclosing binding or select a module-level name. If no suitable enclosing binding exists, the declaration is a syntax error. Reading an enclosing name alone does not require nonlocal.

Choices and common mistakes

Use closures for small, focused state. A class can be clearer when there are several related operations or many fields.

Different calls to the outer function can create independent state. Multiple users of the same returned function share that one closure.

Try it yourself

Create two counters starting at different numbers. Alternate their calls and show that each retains its own value.

Syntax

def counter():
    value = 0
    def next_value():
        nonlocal value
        value += 1
        return value
    return next_value

Examples

Create an independent counter

Persist a value between calls to a returned function.

def make_counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

counter = make_counter()
print(counter(), counter())
  1. make_counter creates count and returns increment. nonlocal lets increment rebind that enclosing count.
  2. The second call observes the value left by the first. The enclosing function need not still be executing for its binding to remain available.
  3. Use a closure for a local sequence generator when a full class would add little clarity.
  4. Expected output: 1 2

Keep factories separate

Demonstrate that each factory call owns a different binding.

def make_counter(start):
    def increment():
        nonlocal start
        start += 1
        return start
    return increment

left = make_counter(0)
right = make_counter(10)
print(left(), right(), left())
  1. The two make_counter calls create separate start bindings. left and right close over different state.
  2. The final left call advances only the first counter. The displayed values reveal the separation.
  3. Separate closures can track independent workflows, but calls on one closure still share its state.
  4. Expected output: 1 11 2

Retain the best value

Update enclosing state only when a better candidate arrives.

def make_best():
    best = None
    def consider(score):
        nonlocal best
        if best is None or score > best:
            best = score
        return best
    return consider

consider = make_best()
print(consider(4), consider(2), consider(7))
  1. None marks the initial absence of a score. The short-circuit condition avoids comparing an integer with None.
  2. Only a larger score rebinds best; a smaller score leaves the retained result unchanged.
  3. This can summarise a stream of measurements while keeping just one value in memory.
  4. Expected output: 4 4 7

Best practices

  • Use closures for small, focused state. A class can be clearer when there are several related operations or many fields.
  • Different calls to the outer function can create independent state. Multiple users of the same returned function share that one closure.

Runtime & versions

Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Python language reference

Specifications & further reading