Python: Sharing global variables between modules and classes therein

34,463

Solution 1

This happens because you are using immutable values (ints and None), and importing variables is like passing things by value, not passing things by reference.

If you made global_mod.x a list, and manipulated its first element, it would work as you expect.

When you do from global_mod import x, you are creating a name x in your module with the same value as x has in global_mod. For things like functions and classes, this works as you would expect, because people (generally) don't re-assign to those names later.

As Alex points out, if you use import global_mod, and then global_mod.x, you will avoid the problem. The name you define in your module will be global_mod, which always refers to the module you want, and then using attribute access to get at x will get you the latest value of x.

Solution 2

from whatever import * is not a good idiom to use in your code -- it's intended for use, if ever, in an interactive session as a shortcut to save some typing. It basically "snapshots" all names from the module at that point in time -- if you ever rebind any of those names, the snapshot will have grown stale and all sort of problems will ensue. And that's only the beginning of the inextricable mess you're signing up for by using the wretched from ... import * construct.

Want my advice? Forget you ever heard about that construct existing and never, ever use it again. Use import global_mod as m and always use thereafter qualified names such as m.x -- qualified names are so much handier and more powerful in Python, than mere barenames, that it ain't even funny. (The as m part of the import statement is totally optional and basically exists for conciseness purposes, or sometimes to work around some issues with name clashes; use it when and if you find it handy, since it has no downsides, but don't feel forced or even urged to use if when you don't feel it's necessary).

Share:
34,463
emish
Author by

emish

Updated on May 17, 2020

Comments

  • emish
    emish almost 4 years

    I know that it's possible to share a global variable across modules in Python. However, I would like to know the extent to which this is possible and why. For example,

    global_mod.py

    x = None
    

    mid_access_mod.py

    from global_mod import *
    
    class delta:
        def __init__(self):
            print x
    

    bot_modif_mod.py

    import mid_access_mod
    import global_mod
    
    class mew:
        def __init__(self):
            global_mod.x = 5
    
    def main():
        m = mew()
        d = mid_access_mod.delta()
    

    This prints None, even though all the modules are sharing the global variable x. Why is this the case? It seems like x is evaluated at mid_access_mod.py before it is assigned in bot_modif_mod.py by mew().

  • user1379351
    user1379351 almost 11 years
    I think your answer here is misleading. The issue not primarily one arising from the use of mutable or immutable types, but rather of using from modulename import * instead of import modulename. If you take emish's code and change global_mod.py to be x = ['starting list'] and then change the reassignment in bot_modif_mod.py to global_mod.x = ['new list'] you'll find that this prints "['starting list']". The real issue, as Alex Martinelli states is that from modulename import * snapshots. I hope other users aren't similarly confused as I was.
  • KFox
    KFox over 10 years
    I believe that what @Ned is tying to say is that, given that x= ['starting list'], one should edit the value by doing x[0] = 'new value', rather than assigning the value to be a completely new list (x = ['new list'])