What does "nonlocal" do in Python 3?

closures, global, nested-function, python, python-nonlocal

Solution

Compare this, without using `nonlocal`:

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

To this, using `nonlocal`, where `inner()`'s `x` is now also `outer()`'s `x`:

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

If we were to use `global`, it would bind `x` to the properly "global" value:

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)
        
    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

Problem

What does `nonlocal` do in Python 3.x? To close debugging questions where OP needs `nonlocal` and doesn't realize it, please use Is it possible to modify variable in python that is in outer, but not global, scope? instead. Although Python 2 is officially unsupported as of January 1, 2020, if for some reason you are forced to maintain a Python 2.x codebase and need an equivalent to `nonlocal`, see nonlocal keyword in Python 2.x.

Original source

Related problems