1

I have a short example python script that I'm calling glbltest.py:

a = [] def fun(): global a a = [20,30,40] print("before ",a) fun() print("after ",a) 

If I run it from the command line, I get what I expect:

$ python glbltest.py before [] after [20, 30, 40] 

I open a python shell and run it by importing, and I get basically the same thing:

>>> from glbltest import * before [] after [20, 30, 4] 

So far so good. Now I comment out those last three lines and do everything "by hand":

>>> from glbltest import * >>> a [] >>> fun() # I run fun() myself >>> a # I look at a again. Surely I will get the same result as before! [] # No! I don't! 

What is the difference between fun() being run "automatically" by the importing of the script, and me running fun() "by hand"?

1 Answer 1

3

global a refers to the name a in the glbltest module's namespace. When you set a by hand, it refers to the name a in the __main__ module's namespace.

When you use from glbltest import * the names in the module are imported into the __main__ module's namespace. Those are different names but refer to the same objects. When you use global a and a = [20,30,40] in the glbltest module, assignment makes a new object that a in glbltest module's namespace now refers to. The name a in the __main__ module still refers to the original object (the empty list).

As a simple example, print the id() of a in the fun() function, and print(id(a)) "by hand" after you set it:

a = [] def fun(): global a print(a, id(a)) a = [20,30,40] print(a, id(a)) # To view the global a object id again def show(): print(a, id(a)) 

"by hand", with comments:

>>> from glbltest import * >>> a # the imported name [] >>> id(a) # its object ID 2056911113280 >>> fun() [] 2056911113280 # start of fun() the object is the same ID [20, 30, 40] 2056902829312 # but assignment changes to new object (different ID) >>> a [] # main a still refers to original object >>> id(a) 2056911113280 >>> show() # glbltest module still sees *its* global a [20, 30, 40] 2056902829312 

Note that if you use mutation vs. assignment to change the existing object. You'll see the change:

a = [] def fun(): global a print(a, id(a)) a.extend([20,30,40]) # modify existing object, not assigning a new object. print(a, id(a)) # To view the global a object id again def show(): print(a, id(a)) 

Now the object IDs remain the same.

>>> from glbltest import * >>> a, id(a) # import object ([], 1408887112064) >>> fun() [] 1408887112064 # before change still the same object [20, 30, 40] 1408887112064 # mutated the *existing* list >>> a, id(a) ([20, 30, 40], 1408887112064) # main's 'a' refers to the same object, same ID >>> show() [20, 30, 40] 1408887112064 # glbltest refers to the same object, same ID 

It's a bit more obvious that the names are different if you just import the module and the module's a can be referred to directly as glbltest.a.

a = [] def fun(): global a a = [20,30,40] 
>>> import glbltest >>> glbltest.a [] >>> a = 5 # main's a >>> a 5 >>> glbltest.a # module's a [] >>> glbltest.fun() >>> a # main's a doesn't change 5 >>> glbltest.a # module's a does. [20, 30, 40] 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.