Python Nonlocal Keyword in Nested Functions

The nonlocal keyword in Python allows inner functions to modify variables defined in an enclosing outer scope without converting those variables into globals. This article explains the exact purpose of nonlocal, how it resolves variable scoping conflicts inside nested functions, how it differs from the global keyword, and how to use it properly with clear code examples.

Understanding the Scope Problem

Python resolves variable names using the LEGB rule, which stands for Local, Enclosing, Global, and Built-in scopes. When working with nested functions, an inner function can freely read variables defined in the outer function. However, the moment you attempt to reassign that variable inside the inner function, Python automatically treats it as a new local variable unless told otherwise.

Consider this example without nonlocal:

def outer():
    count = 0

    def inner():
        count += 1  # UnboundLocalError: local variable 'count' referenced before assignment
        return count

    return inner

In the code above, assigning to count creates a new local variable named count inside inner(). Because the assignment expression references count before assigning to it, Python raises an UnboundLocalError.

How the nonlocal Keyword Works

The nonlocal keyword explicitly declares that a variable refers to a previously bound variable in the nearest enclosing scope, excluding the global scope. This allows you to modify the outer variable's value directly.

def make_counter():
    count = 0

    def counter():
        nonlocal count
        count += 1
        return count

    return counter

my_counter = make_counter()
print(my_counter())  # Outputs: 1
print(my_counter())  # Outputs: 2
print(my_counter())  # Outputs: 3

By placing nonlocal count inside counter(), Python points all operations on count directly to the count variable declared in make_counter(). This pattern is widely used in closures and stateful function decorators to preserve state across multiple function calls without using class instances or global state.

nonlocal vs. global

While both keywords allow modification of variables defined outside the current function, they target entirely different scopes:

Important Restrictions