How does variable scoping work with python imports
Question: I am having difficulty understanding how global variables from a module are
actually imported in another module. Suppose we have a module mod1.py coded as
below:

    
    
    #mod1.py
    var1 = None
    def test():
        global var1
        var1=1
    

* * *

and, another module mod2.py that intends to use mod1.py, as below:

* * *
    
    
    #mod2.py
    from mod1 import *  #This may not be a good coding practice, but it's relevant to my question
    print "var1="+str(var1)
    test()
    print "var1="+str(var1)
    

* * *

When executing mod2, the print statements print:

    
    
    var1=None
    var1=None
    

* * *

which means that the value of var1 that was imported as a result of "from mod1
import *" did not bear any change in mod2 by calling test(). On the other
hand, if I code mod2 as below:

* * *
    
    
    #mod2.py
    import mod1
    print "var1="+str(mod1.var1)
    mod1.test()
    print "var1="+str(mod1.var1)
    

* * *

The first and second print statements print:

    
    
    var1=None
    var1=1
    

* * *

which means that the value of var1 was changed by a call to mod1.test().

Why is that so?


Answer: One common analogy for this is to think of strings tied to balloons. Think of
every assignment statement as tying a string to a balloon. e.g.

    
    
    a = 1  # tie a string "a" to the `1` balloon
    b = a  # tie a string to the same balloon that "a" is tied to.
    

Assigning a new thing to an existing variable is akin to cutting the current
string and tying it to something else:

    
    
    a = 2  # cut string tying "a" to 1 and tie it to the `2` balloon
    

In the first version (`from mod1 import *`) you basically do a whole bunch of
assignment statements:

    
    
    var1 = mod1.var1
    ...
    

Now, you have 2 strings tied to the 1 balloon -- `mod1.var1` and `mod2.var1`.
After you call the `test` function, you cut the string of `mod1.var1` and tie
it to the "2" balloon.

In the second example (`import mod1`), you have a string (`mod2.mod1`) tied to
the `mod1` _module_ , but no explicit string tied to `mod1.var1`. So now when
you re-tie the `mod1.var1` string, you can still look it up the same way --
The string tied to `mod1` hasn't change, only the string from `mod1` to
`mod1.var1`.

