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().
I modified the example to use a list for x, and list assigns (x[0] = ..) as suggested in the top answer, and the print returned the same initial value (None)..This verifies that the "from global_mod import *" is a copy regardless of mutable or not.
As suggested in the comment "import global_mod" works, if "print global_mod.x = is then used in mid_access_mod.
To solve this problem, just change
from global_mod import *
toimport global_mod
.And the new mid_access_mod.py will be:
The reason for that could be found here.
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 namex
in your module with the same value asx
has inglobal_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 thenglobal_mod.x
, you will avoid the problem. The name you define in your module will beglobal_mod
, which always refers to the module you want, and then using attribute access to get atx
will get you the latest value ofx
.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 wretchedfrom ... 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 asm.x
-- qualified names are so much handier and more powerful in Python, than mere barenames, that it ain't even funny. (Theas m
part of theimport
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).As Ned Batchelder mentioned, only the values are shared and not the actual object. If you want to share an object by reference, then you are probably looking
Thread-Local Data
.Eg:
Now, whenever you want to access or change the variable g.population, you will get an updated value of it, provided it is the same thread you are trying to access it from.
Read more in the Python documentation:https://docs.python.org/3/library/threading.html#thread-local-data