Date Tags python

After several years of regular Python use, I really admire that things work how I expect about 90% of the time. To be fair, the other 10% is typically user error. It is easy to overlook nuances in a language, even if you should know better.

I ran into this gotcha in Python recently: when importing a global variable from a module explicitly by name, that variable will be bound to the local namespace. If that bound global is of immutable type (such as the built-in integer type), changes to that variable will not be reflected in the original namespace. Whew, that was an exhausting explanation, an example demonstrates the issue nicely.

Consider the following three Python files, mymod.py, main1.py, and main2.py:


mymod.py

foo = 10
def func():
    print "info5:", foo

Our example module (mymod.py) defines a global variable and function that uses that global.


main1.py

from mymod import foo, func
_ = None; print "info1:", [_ for _ in globals() if not _.startswith("_")]
print "info2:", foo, id(foo)
func()
foo += 1
print "info3:", foo, id(foo)
func()

Our first example of using mymod imports the global and function by name. The global is updated by main1.py and then the function is called. However, because the imported foo was updated, it no longer points to the same object as foo in the mymod namespace. The output of this script is the following:

info1: ['func', 'foo']
info2: 10 11159084
info5: 10 11159084
info3: 11 11159072
info5: 10 11159084

main2.py

import mymod
_ = None; print "info1:", [_ for _ in globals() if not _.startswith("_")]
print "info2:", mymod.foo, id(mymod.foo)
mymod.func()
mymod.foo += 1
print "info3:", mymod.foo, id(mymod.foo)
mymod.func()

Our second example of using mymod imports only the module. Since the foo global is updated and accessed via the mymod namespace, the changes will be reflected both in main2 and mymod. The output of this script is the following:

info1: ['mymod']
info2: 10 32982572
info5: 10 32982572
info3: 11 32982560
info5: 11 32982560

Please note that this gotcha only applies if the global variable is of immutable type. If the variable is mutable, such as a list or dictionary, this particular issue would not be expressed.

Hi, I am Jeff Rimko!
A computer engineer and software developer in the greater Pittsburgh, Pennsylvania area.