RetiredRon
Posts: 2
Joined: Wed Aug 21, 2019 7:05 pm

Confused by Global?

Thu Aug 22, 2019 2:43 pm

I' m having trouble with global variable declarations. I understand that they must be declared inside a function if their value will be modified and used outside the function, but the following code snippet, which I pulled from a Python learning site, has me baffled:

Code: Select all

#start of code snippet:
def foo():
    x = 20

    def bar():
        global x
        x = 25
    
    print("Before calling bar: ", x)
    print("Calling bar now")
    bar()
    print("After calling bar: ", x)

foo()
print("x in main : ", x)
#end of code snippet

This results in the following output:

Before calling bar: 20
Calling bar now
After calling bar: 20
x in main : 25

I thought the fact that “x” is not changing after calling the bar function might have something to do with nesting the bar function within the foo function, so I moved it from within the foo function to the outside at the same level as the foo function. But running the modified version still generated the same result.

So why, after declaring x as global in the bar function, is its value not changed on return? And why is it then changed in the main program?

Any help appreciated!

User avatar
rpdom
Posts: 15199
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Confused by Global?

Thu Aug 22, 2019 6:06 pm

The function foo is using a local version of x, but bar is using a global version. When bar is run it updates the global version which won't affect the local version of x used in foo.

User avatar
MrYsLab
Posts: 375
Joined: Mon Dec 15, 2014 7:14 pm
Location: Noo Joysey, USA

Re: Confused by Global?

Thu Aug 22, 2019 6:18 pm

If you use a class instead of a collection of individual procedures, you can avoid the whole global mess. Here is a great turorial: https://realpython.com/python3-object-o ... ogramming/

I took the liberty to convert your program using a class:

Code: Select all

class PlayTime:
    # a class variable
    x = 33

    def __init__(self):
        # an instance variable
        self.x = 20

    def bar(self, value):
        self.x = value


p = PlayTime()

print("Before calling bar: ", PlayTime.x, p.x)
print("Calling bar now")
p.bar(99)
print("After calling bar: ", PlayTime.x, p.x)
Here is the result of the run:

Code: Select all

Before calling bar:  33 20
Calling bar now
After calling bar:  33 99

hippy
Posts: 5957
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Confused by Global?

Thu Aug 22, 2019 11:39 pm

Consider this ...

Code: Select all

global_x = 0

def foo():
  foo_x = 20

  def bar():
    bar_x = 25

  print("Before calling bar: ", foo_x)
  bar()
  print("After calling bar: ", foo_x)

foo()
print("After calling foo: ", global_x)
Each use of "x" in your original code is refering to a particular "_x" variable, and those are effectively the internal names even though you are using only a simple "x" for all of them.

By adding a "global x" in the bar() routine, it is making "bar_x" synonymous with "global_x". Changing "x" in bar() changes "bar_x" which is actually "global_x".

The "x" in the foo() routine refers to "foo_x" which wasn't changed. But back at the outer code after calling foo() the "x" there refers to "global_x" which was changed.

RetiredRon
Posts: 2
Joined: Wed Aug 21, 2019 7:05 pm

Re: Confused by Global?

Tue Aug 27, 2019 2:29 pm

To: rpdom and hippy
Thanks for your replies. I think I understand this now, thanks to your explanations.

To: MrYsLab:
I'm just starting to learn OOP so don't yet understand your code using classes, etc. I'll return to it once I've got the basics nailed down.
I appreciate the link to the OOP tutorial. It looks like a great place to start!
Thanks!

Return to “Python”