The nonlocal Keyword in Python 2026
The nonlocal keyword allows an inner (nested) function to modify a variable from its immediately enclosing (outer) function’s scope. It is the nested-function counterpart to the global keyword and is essential when working with closures and factory functions.
TL;DR — Key Takeaways 2026
nonlocallets inner functions modify variables in the enclosing function scope- It only works inside nested functions (not at module level)
- Commonly used in closures, counters, and stateful inner functions
- Prefer returning values or using classes when possible
1. Basic Usage of nonlocal
def outer():
count = 0
def inner():
nonlocal count # Allows modification of outer's 'count'
count += 1
return count
return inner
counter = outer()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
2. Practical Example – Stateful Closure
def make_accumulator(initial: int = 0):
total = initial
def add(value: int) -> int:
nonlocal total
total += value
return total
return add
acc = make_accumulator(100)
print(acc(10)) # 110
print(acc(25)) # 135
print(acc(-5)) # 130
3. Best Practices in 2026
- Use
nonlocalonly when you need to modify enclosing scope variables - Keep the outer function small and focused when using
nonlocal - Document the use of
nonlocalclearly - Consider classes or returning a mutable object when state becomes complex
- Combine with type hints for better readability
What nonlocal Changes
nonlocal tells Python that a name in a nested function refers to a variable in the nearest enclosing function, not a new local variable and not a global. It is needed only when the inner function rebinds the name, for example with = or +=.
Without nonlocal, an assignment inside the inner function creates a local name, and a read before it fails with UnboundLocalError. Mutating an outer list or dictionary does not need nonlocal, because the name itself is not rebound.
nonlocal can only refer to function scopes. Using it for a module-level name raises a SyntaxError, because module names are global, not enclosing.
The keyword is most useful for small closures that keep a running value, such as a counter or a running total.
Worked Example: Rebinding Versus Mutating
We compare a counter that needs nonlocal with a log list that does not.
def make_tracker():
count = 0
log = []
def track(event):
nonlocal count # rebinding needs nonlocal
count += 1
log.append(event) # mutation does not
return count, list(log)
return track
track = make_tracker()
print(track("start"))
print(track("click"))
try:
exec("x = 1\ndef f():\n nonlocal x\n")
except SyntaxError as e:
print("SyntaxError:", e.msg)
The tracker returns (1, ['start']) and then (2, ['start', 'click']). Only count needed nonlocal. Trying to use nonlocal for a module-level name raises a SyntaxError saying no binding for nonlocal 'x' found.
Practical Tips
If a closure needs several pieces of changing state, a small class with attributes is often clearer than several nonlocal names. The class also makes the state visible for debugging.
Write a short test that calls the closure several times and checks the result after each call. Bugs with nonlocal usually show up only on the second call, when the old value is used.
Keep the enclosing variable's name distinct from any global name, so readers do not confuse the two scopes.
Remember that each call of the factory creates a separate state, which makes closures easy to reset by simply creating a new one.
In Python 3, nonlocal replaces older tricks such as storing a counter in a one-element list. Use the keyword in new code because it states the intent directly.
A quick test calling the closure twice confirms that the value persists.
Common Mistakes
- Using nonlocal when you only mutate a list or dict.
- Using nonlocal for module variables instead of global.
- Chaining many nonlocal names, which hides state.
- Forgetting that each factory call creates a fresh variable.
Quick Summary
- nonlocal rebinds a variable in an enclosing function.
- Mutation needs no declaration.
- It cannot refer to module names.
- Ideal for small counters and totals.
Conclusion
The nonlocal keyword is a clean and powerful tool for working with nested functions and closures. In 2026, it is commonly used to create simple stateful functions and factories. However, for more complex state management, classes or returning objects are often preferred for better maintainability.
Next steps:
- Review your nested functions and use
nonlocalwhere you need to modify enclosing variables