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一个与x
在global_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某种方式。