No binding for nonlocal

In the code below, doesn’t it skip the global scope until it finds a local variable in a higher containing scope?

x = 'monty'
def outer():
    x = 'python'
    def inner1():
        global x
        x = 'holy'
        def inner2():
            nonlocal x
            x = 'grail'
            print('inner2', x)
        inner2()
    inner1()
outer()

PS - This is me trying things out and not planning on writing actual code this way.

At nonlocal x you get a syntax error, since x at that point is bound to a global variable (x started out as local variable in the function, but you rebound it).

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals.

The docs spells out very clearly that

Names listed in a nonlocal statement, unlike those listed in a global statement, must refer to pre-existing bindings in an enclosing scope… Names listed in a nonlocal statement must not collide with pre-existing bindings in the local scope.

See: 7. Simple statements — Python 3.12.0 documentation

2 Likes