Python:在其中的模块和类之间共享全局variables

我知道可以在Python中跨模块共享一个全局variables。 但是,我想知道这是可能的程度,为什么。 例如,

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() 

这将打印None,即使所有模块共享全局variablesx。 这是为什么? 在me_m()被分配到bot_modif_mod.py之前,似乎x在mid_access_mod.py处被评估。

发生这种情况是因为你使用了不可变的值(int和None),导入variables就像是按值传递事物,而不是通过引用传递事物。

如果你创build了global_mod.xa列表,并且操作了它的第一个元素,它就可以像你期望的那样工作。

当您from global_mod import x ,您将在模块中创build一个与xglobal_mod具有相同值的名称x 。 对于像函数和类这样的东西,这可以像你所期望的那样工作,因为人们(通常)以后不会重新分配这些名字。

正如Alex指出的那样,如果使用import global_mod ,然后使用global_mod.x ,则可以避免该问题。 您在模块中定义的名称将是global_mod ,它总是指您想要的模块,然后使用属性访问获取x将获得最新的x值。

from whatever import * 不是一个很好的习惯用法在你的代码 – 它的目的是为了使用,如果有的话,在交互式会话中作为一个快捷方式来节省一些打字。 它在这个时候基本上“模拟”了模块中的所有名字 – 如果你重新绑定了这些名字,快照就会变得陈旧,并且会出现各种各样的问题。 而这只是你使用可怜的from ... import *构造注册的难解之谜的from ... import *

希望我的build议? 忘记你曾经听说过这个构build存在,永远不会再使用它。 使用import global_mod as m并且总是使用像mx这样的限定名,在Python中,合法的名字比Python更简单,function更强大,而不是单纯的名字,甚至不好笑。 ( import语句中的部分内容是完全可选的,基本上是为了简洁目的而存在的,或者有时是为了解决与名称冲突有关的一些问题;如果您发现方便,则使用它,因为它没有缺点,但不感觉被迫,甚至要求使用,如果当你不觉得这是必要的)。

我修改了这个例子,使用列表中的x,列表赋值(x [0] = ..)如上面的答案build议,并打印返回相同的初始值(None)。这validation了“from global_mod导入*“是一个副本,不pipe是否可变。

正如在注释“import global_mod”中所build议的那样,如果“print global_mod.x =”然后在mid_access_mod中使用。

正如纳德·巴切尔德(Ned Batchelder)所提到的,只有价值观是共同的,而不是实际的客体 如果你想通过引用来共享一个对象,那么你可能正在寻找Thread-Local Data

例如:

 import threading g = threading.local() g.population = '7 Billion' 

现在,只要你想访问或者更改variablesg.population,你就会得到一个更新的值,只要它是你想要访问的同一个线程。

阅读Python文档中的更多内容: https : //docs.python.org/3/library/threading.html#thread-local-data

要解决这个问题,只需from global_mod import *改为import global_mod

新的mid_access_mod.py将是:

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

原因可以在这里find。

由于引用和名称绑定在Python中的工作方式,如果您想要更新模块中的某个符号(例如foo.bar),并从该模块外部获取其他导入代码“see”,则必须导入foo a某种方式。