Why do nonlocal declarations take precedence over global declarations within a function?

Asked 2 years ago, Updated 2 years ago, 46 views

def scope_test():
    def do_local():
        spam="local spam"
    def do_nonlocal():
        nonlocal spam
        spam="non-local spam"
    def do_global():
        global spam
        spam="global spam"
    spam="test spam"
    do_local()
    print("After local assignment:",spam)
    do_nonlocal()
    print("After nonlocal assignment:",spam)
    do_global()
    print("After global assignment:",spam)

scope_test()
print("Inglobal assignment:",spam)

Here's the output:

After local assignment:test spam
After nonlocal assignment—non-local spam
After global assignment—non-local spam
global scope:global spam

However, I do not understand why it is "After global assignment: non-local spam".Could you please explain very simply why it is next to do_global():global spam, but not non-local spam, so that even beginners can understand it?

python python3

2022-09-30 21:29

4 Answers

A total of three spam variables appear in the program, but this is what happens when you add comments to distinguish them.

def scope_test():
    def do_local():
        spam="local spam"#spam1
    def do_nonlocal():
        nonlocal spam#spam2
        spam="non-local spam"
    def do_global():
        global spam#spam3
        spam="global spam"
    spam="test spam"#spam2
    do_local()
    print("After local assignment:",spam)#spam2
    do_nonlocal()
    print("After nonlocal assignment:",spam)#spam2
    do_global()
    print("After global assignment:",spam)#spam2

scope_test()
print("Inglobal assignment:",spam)#spam3

do_local does not affect the variable spam (spam2) declared in scope_test because do_local is of course just declaring and substituting the local variable.

do_non_local uses nonlocal spam to declare that it uses the nearest variable spam (in this case, spam2) in the outer scope except the global scope.Therefore, after running do_non_local, the value of spam2 is "non-local spam".

(Global scope is the outermost scope)

Finally, do_global declares that global spam uses the global scope variable spam.Although the code does not have a declaration of the global variable spam, the global variable spam (spam3) is created when you run spam="global spam" within do_global.

In the end, do_global does not affect spam2, so "non-local spam" is printed.


2022-09-30 21:29

I don't know if it's super easy, but simply put

print("After global assignment:",spam)

This is running within the scope of the scope_test() function, so it prints nonlocal spam instead of global.As a hint, if you remove the indentation in this line, it will no longer run in scope_test() but in a global scope, so it will print "global spam".

do_global() certainly updates the global scope spam by substituting, but that doesn't mean subsequent

print("After global assignment:",spam)

does not run at the global scope.This means that updating and evaluating values is not related.In fact, this statement is called at a nonlocal scope.


2022-09-30 21:29

Do_local is not the heart of the problem, so I'll skip it.

def scope_test():    
    spam="local spam"
    def do_nonlocal():     
        nonlocal spam
        spam="non_local spam"        
    def do_global():
        global spam
        spam="global spam"

    do_nonlocal()
    print("After non_local assignment:",spam)
    do_global()
    print("After global assignment:",spam)
scope_test()
print("Inglobal assignment:",spam)

Result 1

After non_local assignment:non_local spam
After global assignment: non_local spam
global assignment:global spam

The code above is equivalent to this code.

spam="global spam"
def scope_test():    

    def do_nonlocal():     
        nonlocal spam
        spam="non_local spam"        
    def do_global():
        pass
    spam="test spam"
    do_nonlocal()
    print("After non_local assignment:",spam)
    do_global()
    print("After global assignment:",spam)
scope_test()
print("Inglobal assignment:",spam)

Result 2

After non_local assignment:non_local spam
After global assignment: non_local spam
global assignment:global spam

The global declaration means that you defined a variable at the global scope = top level.

This is what happens when even the nonlocal declaration passes.

spam="global spam"
def scope_test():    
    def do_nonlocal():     
        pass     
    def do_global():
        pass
    do_nonlocal()
    print("After non_local assignment:",spam)
    do_global()
    print("After global assignment:",spam)
scope_test()
print("Inglobal assignment:",spam)

Result 3

After non_local assignment:global spam
After global assignment —global spam
global assignment:global spam

Conditions for Using Nonlocal Declaration
- Must be declared within nested functions.(here under do_nonlocal)
·Variables must be defined outside the scope before declaration (under scope_test)
·This variable is not a global declaration.

If you write a nonlocal declaration, the variable will no longer be treated as a local variable under the nested function.

def do_global():
    global spam
    spam="global spam"

My biggest question
In , after calling do_nonlocal(), you are calling do_global(), but why
Will the spam not be overwritten?
This spam is defined the same way as result 2, so do_global() cannot overwrite it.


2022-09-30 21:29

Simply put,
only if there is a variable in the function that has the same name as global. Each variable is transformed into a different variable.
So it's not that non-local is preferred.
Global is just not involved in that variable.
Try

do_local()
print("After local assignment:",spam)
do_nonlocal()
print("After nonlocal assignment:",spam)

Try to erase and run .You will understand what it means.


2022-09-30 21:29

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.