nonlocal

A nested function can read its outer function’s variables for free. To assign to one, declare it nonlocal — otherwise the assignment creates a new local.

FunctionsPython 3.0+Live demo
nonlocal
def outer():
    x = 0
    def inner():
        nonlocal x
        x += 1
several names
nonlocal a, b
Use for
Counters, accumulators and flags kept in a closure
Result
a declaration — no value; the name refers to the nearest enclosing function’s variable
Pairs with
def (nested), global, lambda, decorators
Watch out
the name must already be bound in an enclosing FUNCTION — module globals do not count

Demo

Live evaluation
Each call to c rebinds count in make_counter’s scope, which outlives the call that created it.
Try:
Inputs
startintstarting value
Code
def make_counter(start):
    count = start
    def bump():
        nonlocal count
        count += 1
        return count
    return bump
c = make_counter(0)
(c(), c(), c())
Result
(1, 2, 3)

make_counter has already returned when c() runs, yet count survives: the inner function holds a reference to the variable (a closure cell), and nonlocal lets it write to that cell instead of creating a fresh local.

Syntax slots

NameTypeRequiredDescription
namenameyesOne or more identifiers bound in an enclosing function (not the module). Resolved at compile time.

Common patterns

Counter closure
State without a class.
def make_counter():
    count = 0
    def bump():
        nonlocal count
        count += 1
        return count
    return bump
Decorator that counts calls
The wrapper updates a variable of the decorator.
def counted(func):
    calls = 0
    def wrapper(*args, **kwargs):
        nonlocal calls
        calls += 1
        return func(*args, **kwargs)
    return wrapper
Flag set by a callback
An inner helper reports back to its outer function.
def scan(items):
    found = False
    def check(x):
        nonlocal found
        if x < 0:
            found = True
    for x in items:
        check(x)
    return found

Examples

1. A counter closure
def make_counter(): count = 0 def bump(): nonlocal count count += 1 return count return bump c = make_counter() c() c()
Returns
2
2. Reading needs no declaration
def outer(): x = 10 def inner(): return x + 1 return inner() outer()
Returns
11
3. Nearest enclosing function wins
def a(): x = 'a' def b(): x = 'b' def c(): nonlocal x x = 'c' c() return x return b(), x a()
Returns
('c', 'a')
4. Mutating needs no nonlocal
def make(): seen = [] def add(v): seen.append(v) return seen return add add = make() add(1) add(2)
Returns
[1, 2]
5. The name must exist in an enclosing function
compile('def f():\n nonlocal x', '<demo>', 'exec')
Returns
SyntaxError: no binding for nonlocal 'x' found
6. Not at module level
compile('nonlocal x', '<demo>', 'exec')
Returns
SyntaxError: nonlocal declaration not allowed at module level
7. Closures are separate
def make_counter(): count = 0 def bump(): nonlocal count count += 1 return count return bump c1, c2 = make_counter(), make_counter() (c1(), c1(), c2())
Returns
(1, 2, 1)

Pitfalls

1. Updating an outer variable with +=
total += n assigns, so total becomes local to add — and is read before it has a value.
no declaration
def make_acc():
    total = 0
    def add(n):
        total += n
        return total
    return add
make_acc()(5)
UnboundLocalError: cannot access local variable 'total' where it is not associated with a value
nonlocal total
def make_acc():
    total = 0
    def add(n):
        nonlocal total
        total += n
        return total
    return add
make_acc()(5)
5
2. A plain assignment silently creates a local
No error at all — the inner function just sets its own variable, and the outer one never changes.
assignment only
def outer():
    status = 'idle'
    def start():
        status = 'running'
    start()
    return status
outer()
'idle'
nonlocal status
def outer():
    status = 'idle'
    def start():
        nonlocal status
        status = 'running'
    start()
    return status
outer()
'running'
3. nonlocal for a module-level variable
nonlocal only searches enclosing functions. A module variable needs global.
nonlocal
compile('x = 0\ndef f():\n    nonlocal x\n    x = 1', '<demo>', 'exec')
SyntaxError: no binding for nonlocal 'x' found
global
x = 0
def f():
    global x
    x = 1
f()
x
1

When to use

Use it
  • Small stateful closures: counters, accumulators, memo flags
  • Decorators that keep per-function state
  • Helper functions nested inside a function that need to update its variables
Reach for something else
  • State with several fields or methods → a class
  • Module-level variables → global (or better, parameters and return values)
  • Only mutating an outer list or dict → no declaration needed

Notes

CPython impl
The shared variable lives in a cell object: the outer function uses MAKE_CELL / STORE_DEREF, the inner one LOAD_DEREF / STORE_DEREF
Scope
nonlocal skips the local scope and searches enclosing function scopes from the nearest outward; class bodies and the module are never searched
Python 2
Python 2 had no nonlocal — the usual workaround was a mutable container like count = [0]

FAQ

global name refers to the module-level variable. nonlocal name refers to the variable of the nearest enclosing function that binds it. Both let you assign to a name that would otherwise become local.