Ad

Why Is Nonlocal Keyword Being 'interrupted' By A Global Keyword?

- 1 answer

I'm a beginner programmer trying to learn python, and I have come across the topic of scopes. I came across the error 'no binding for nonlocal var_name found' when executing the bottom-most code. Can someone explain why is the nonlocal keyword unable to 'look past' the intermediate function and into the outer function?


#this works
globe = 5


def outer():
    globe = 10
    def intermediate():

        def inner():
            nonlocal globe
            globe = 20
            print(globe)
        inner()
        print(globe)
    intermediate()
    print(globe)


outer()

globe = 5


def outer():
    globe = 10
    def intermediate():
        global globe #but not when I do this
        globe = 15
        def inner():
            nonlocal globe #I want this globe to reference 10, the value in outer()
            globe = 20
            print(globe)
        inner()
        print(globe)
    intermediate()
    print(globe)


outer()
Ad

Answer

Expressions involving the nonlocal keyword will cause Python to try to find the variable in the enclosing local scopes, until it first encounters the first specified variable name.

The nonlocal globe expression will have a look if there is a variable named globe in the intermediate function. It will encounter it, in the global scope however, so it will presume it has reached the module scope and finished searching for it without finding a nonclocal one, hence the exception.

By declaring the global globe in the intermediate function you pretty much closed the path to reach any nonlocal variables with the same name in the previous scopes. You can have a look at the discussion here why was it "decided" to be implemented this way in Python.

If you want to make sure that the variable globe is or is not within the local scope of some function, you can use the dir() functions, because from Python docs:

Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object.

Ad
source: stackoverflow.com
Ad