Definitions - Nonlocal Variables in Python 2026

Writing Functions Mar 16, 2026

Definitions - Nonlocal Variables in Python 2026

A nonlocal variable is a variable that belongs to the enclosing (outer) function’s scope and is accessed or modified from within a nested (inner) function. The nonlocal keyword is used to explicitly tell Python that we want to refer to the variable in the nearest enclosing scope rather than creating a new local variable.

TL;DR — Key Definitions 2026

  • Nonlocal Variable: A variable defined in an enclosing function that can be read or modified by a nested function
  • nonlocal Keyword: Declares that a name refers to a variable in the nearest enclosing scope (not global, not local)
  • Enclosing Scope: The scope of the function that contains the nested function
  • Closure: A nested function that "remembers" its nonlocal variables even after the outer function has returned

1. Clear Definition with Example


def outer():
    x = 10                    # This is a nonlocal variable for the inner function
    
    def inner():
        nonlocal x            # Explicitly refer to the variable in outer scope
        x += 5                # Modifies the nonlocal variable
        print("Inside inner:", x)
    
    inner()
    print("Inside outer after inner:", x)

outer()
# Output:
# Inside inner: 15
# Inside outer after inner: 15

2. Without nonlocal (Common Mistake)


def outer():
    x = 10
    
    def inner():
        x = 20                # This creates a NEW local variable!
        print("Inside inner:", x)
    
    inner()
    print("Inside outer:", x)   # Still 10 - unchanged

outer()

3. Best Practices for Nonlocal Variables (2026)

  • Always use the nonlocal keyword when you intend to modify a variable from the enclosing scope
  • Keep the number of nonlocal variables small for readability
  • Document the purpose of each nonlocal variable clearly
  • When state becomes complex, prefer a class over many nonlocal variables
  • Use type hints on both outer and inner functions

Local, Enclosing, Global and Built-In Names

Python looks up a name in four scopes, in this order: Local, Enclosing, Global and Built-in, often remembered as LEGB. A nonlocal variable is a name in the enclosing scope, that is, a local variable of an outer function that an inner function uses.

Reading an enclosing variable needs no declaration. Rebinding it requires the nonlocal statement; otherwise the assignment creates a new local name in the inner function.

The built-in scope holds names like len and print. Defining your own variable called len hides the built-in in that scope, which is a common source of confusing errors.

Seeing which scope a name comes from makes closures, decorators and many error messages much easier to understand.

Worked Example: One Name in Four Scopes

We define the same name in several scopes and print which value each function sees.

x = "global"

def outer():
    x = "enclosing"
    def inner_read():
        return x                    # E: found in outer
    def inner_local():
        x = "local"                 # L: new local name
        return x
    def inner_rebind():
        nonlocal x
        x = "rebound enclosing"
    print(inner_read(), "|", inner_local())
    inner_rebind()
    print("outer now sees:", x)

outer()
print("module still sees:", x)
print(len("abc"), "uses the built-in len")

inner_read finds the enclosing value and inner_local creates its own local. After inner_rebind uses nonlocal, outer sees rebound enclosing. The module x is unchanged, and len still comes from the built-in scope.

Practical Tips

Use a linter such as pylint or ruff to catch names that shadow built-ins. These tools flag variables called list or id before they cause confusing errors.

When a name behaves unexpectedly, print locals() inside the function to see which names are local at that point.

Common Mistakes

  • Shadowing built-ins such as list, len or id.
  • Expecting an inner assignment to change the outer variable.
  • Confusing nonlocal with global.
  • Reusing one name for different meanings in nested scopes.

Quick Summary

  • Lookup order is Local, Enclosing, Global, Built-in.
  • Nonlocal variables live in an enclosing function.
  • Rebinding them needs nonlocal.
  • Avoid shadowing built-in names.

Conclusion

Understanding nonlocal variables is essential for working effectively with nested functions and closures in Python. The nonlocal keyword clearly signals your intention to modify a variable from the enclosing scope rather than creating a local one. In 2026, proper use of nonlocal variables leads to cleaner, more predictable, and maintainable code.

Next steps:

  • Review your nested functions and ensure every reassignment of enclosing variables uses the nonlocal keyword

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices