Python Forum
Understanding Scoping in Python
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Understanding Scoping in Python
#1
I was reading Python docs and encountered this example under "Scope and Namespaces".
def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal 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("In global scope:", spam)
The output to this code is
Output:
After local assignment: test spam After nonlocal assignment: nonlocal spam After global assignment: nonlocal spam In global scope: global spam
My question is, why in output, it is
Output:
After global assignment: nonlocal spam
according to me it should be
Output:
After global assignment: global spam
as spam become a global variable after calling do_global(), and value becomes spam = "global spam"
Reply
#2
Because scope_test already has local variable name spam.
scope looks up local spam first. If not exist then looks for global spam.

spam = "global"

def global_spam():
    print(spam)

def local_spam():
    spam = "local"
    print(spam)

local_spam()
global_spam()
99 percent of computer problems exists between chair and keyboard.
Reply
#3
(Aug-06-2018, 02:24 PM)Windspar Wrote: Because scope_test already has local variable name spam.
scope looks up local spam first. If not exist then looks for global spam.

spam = "global"

def global_spam():
    print(spam)

def local_spam():
    spam = "local"
    print(spam)

local_spam()
global_spam()


Hi Windspar,
Thanks for your explanation,but let me be more specific about my problem
I know that the scoping in python works by LEGB rule,

But when do_global() is called, control finds that do_global() is creating a global variable spam, which is priorly created in scope_test(). So why the variable spam in scope_test is not get overridden by spam variable of do_global(), as it happened when we called do_nonlocal() function (there value of spam = "test spam" became spam = "nonlocal spam",as you can see in the output)
Reply
#4
Because global spam only brings in global scope variables. Not non local variables.

# This is global scope area
spam = "global scope"

def print_spam():
    print(spam)

# soon as you get into a function. It a local variable.
def spam_it():
    def update_spam():
        # grabs  spam from 1 layer down.
        nonlocal spam
        spam = "nonlocal"

    def update_global():
        global spam
        spam = "global scope change"

    print_spam()
    spam = "local"
    print(spam)
    update_spam()
    print(spam)
    update_global()
    print_spam()

spam_it()
99 percent of computer problems exists between chair and keyboard.
Reply
#5
(Aug-06-2018, 05:16 PM)Windspar Wrote: Because global spam only brings in global scope variables. Not non local variables.

# This is global scope area
spam = "global scope"

def print_spam():
    print(spam)

# soon as you get into a function. It a local variable.
def spam_it():
    def update_spam():
        # grabs  spam from 1 layer down.
        nonlocal spam
        spam = "nonlocal"

    def update_global():
        global spam
        spam = "global scope change"

    print_spam()
    spam = "local"
    print(spam)
    update_spam()
    print(spam)
    update_global()
    print_spam()

spam_it()


Okay. Thanks Windspar for your explanation. I understand now.
Reply
#6
There are three different spam variables. A local spam, within do_local(), a local spam, within scope_test() (which is non-local for enclosed functions), and a global spam, which doesn't exist until after do_global() is called. do_global() creates a new variable in the global scope, but it doesn't change any of the other spams that already exist in other scopes. After do_global() is called, referencing spam uses the local version, which is set to "nonlocal spam" at that time.

If print(spam) were to return "global spam", that would violate scoping, as there's a local spam that exists.

...and that's why you avoid having variables with the same name. It adds unneeded confusion. It's highly unlikely that all three of those refer to the same thing, which means they're all poor choices for a variable name, as none actually describe what a spam is.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Understanding venv; How do I ensure my python script uses the environment every time? Calab 1 2,158 May-10-2023, 02:13 PM
Last Post: Calab
  New to python/coding Need help on Understanding why this code isn't working. Thanks! mat3372 8 1,664 May-09-2023, 08:47 AM
Last Post: buran
  Understanding Python classes PythonNewbee 3 1,150 Nov-10-2022, 11:07 PM
Last Post: deanhystad
  Understanding Python super() for classes OmegaRed94 1 1,793 Jun-09-2021, 09:02 AM
Last Post: buran
  Better Understanding Of Object Orientation In Python JoeDainton123 3 2,419 Aug-30-2020, 02:49 PM
Last Post: deanhystad
  Understanding Python's Import Engine MysticaL 1 2,125 Feb-07-2020, 11:26 PM
Last Post: snippsat
  Help with understanding a python package pyhill00 4 2,966 Mar-21-2019, 12:42 AM
Last Post: Larz60+
  Understanding if Statements in Python Kathleen 1 2,385 Mar-05-2019, 07:55 PM
Last Post: Yoriz
  Weird scoping error Stef 3 2,840 Jan-20-2019, 04:36 PM
Last Post: Stef
  Python Iteration Understanding giteepag 3 2,669 Jul-26-2018, 02:23 PM
Last Post: perfringo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020