Stateful closures
Maintain private mutable state across calls without exposing a module-level variable.
Python · Const
The nonlocal statement lets nested code rebind names from an enclosing function scope. It requires each name to already exist in a nonlocal enclosing scope and selects the nearest matching binding.
Place nonlocal inside a nested function or class body to make listed names refer to existing bindings in enclosing function scopes. Assignments then update that enclosing binding instead of creating a new local name.
nonlocal identifier ("," identifier)*| Name | Type | Description |
|---|---|---|
identifier | name | One or more identifiers that must already be bound in an enclosing nonlocal scope. |
def make_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
counter = make_counter()
print(counter())
print(counter())The nested function updates the binding created in make_counter, so successive calls retain and increment the same counter.
Maintain private mutable state across calls without exposing a module-level variable.
Let a nested callback update a value owned by its factory function.
Share and update a binding between nested functions in a controlled lexical scope.
nonlocal makes listed identifiers refer to names already bound in an enclosing nonlocal scope. It allows nested code to rebind those names rather than creating locals.
Follow-up: How is the target chosen when several enclosing scopes bind the name? The nearest enclosing nonlocal binding is selected.
The name must already be bound in an enclosing function scope. If no such scope exists, compilation raises SyntaxError.
Follow-up: Can nonlocal be used at module scope? No; there is no enclosing function scope there, so it is invalid.
The declaration applies throughout the function or class body, and using or assigning the name before its declaration is a SyntaxError.
Follow-up: What happens if the nested scope assigns without nonlocal? The assignment creates or targets a local binding instead of rebinding the outer name.
globalscopeenclosing scopelocal namespace