How can the most inner function access the non-local variable in the most outer function in Python?

193 Views Asked by At

inner() can access the non-local variable x in middle() with nonlocal x:

def outer():
    x = 0
    def middle():
        x = 5 # <- Here
        def inner():
            nonlocal x # Here
            x += 1
            print(x) # 6
        inner()
    middle()
outer()

Now, how can inner() access the non-local variable x in outer()?

def outer():
    x = 0 # <- Here
    def middle():
        x = 5
        def inner():
            x += 1
            print(x) # How to print 1?
        inner()
    middle()
outer()
1

There are 1 best solutions below

0
On

Reading PEP 3104 which introduced the nonlocal keyword, we learn two things:

  1. The inspiration was in part the ability of other languages to refer to names in an enclosing scope, specifically because they distinguish between assignment and declaration.

    This ability is limited to referring to the next outer declaration in those languages, and there's no way to look past an intermediate redeclaration. This is known as "name hiding" or "shadowing".

    So, nonlocal was never really intended to do what you ask.

  2. There was in fact a proposal to allow this with a syntax like .x for one scope out, ..x for two scopes out, etc.

    This was rejected as error-prone, and no other proposal tried to support that ability.

You can't do what you want directly in Python, and you can't do it in any of the languages that inspired nonlocal either. Best to just stop redeclaring the same name.

There is however an ugly workaround, described in the PEP: manually re-exporting a name with a namespace object.