Python:在模块和类之间共享全局变量
我知道在Python中可以在不同的模块之间共享一个全局变量。不过,我想了解这种共享的范围有多大,以及原因是什么。例如,
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,尽管所有模块都在共享全局变量x。为什么会这样呢?看起来在mid_access_mod.py中,x的值是在bot_modif_mod.py的mew()函数给它赋值之前就被使用了。
5 个回答
我把例子改成用列表来表示x,并且按照最上面的回答建议使用了列表赋值(x[0] = ..),结果打印出来的还是最开始的值(None)。这证明了“from global_mod import *”是复制的,不管是可变的还是不可变的。
正如评论中提到的,“import global_mod”是有效的,如果在mid_access_mod中使用“print global_mod.x =”。
from whatever import *
这个写法在你的代码中不太好,它主要是为了在交互式会话中省事而设计的。简单来说,它会把那个模块里所有的名字都“快照”下来,记录在那一刻的状态。如果你之后改变了这些名字,之前的快照就会过时,可能会引发各种问题。这只是使用这个糟糕的 from ... import *
方式所带来的麻烦的开始。
想听我的建议吗?忘掉这个写法的存在,永远不要再用它。你可以用 import global_mod as m
,然后在后面的代码中总是使用带前缀的名字,比如 m.x
。在Python中,带前缀的名字要方便和强大得多,比起简单的名字来说,简直没法比。(as m
这个部分是可选的,主要是为了让代码更简洁,或者有时候是为了避免名字冲突;如果你觉得它方便就用,但如果觉得没必要,也不要强迫自己使用)。
这个问题发生是因为你使用的是不可变的值(比如整数和None),而导入变量就像是按值传递东西,而不是按引用传递。
如果你把global_mod.x改成一个列表,并且操作它的第一个元素,那就会像你预期的那样工作。
当你使用from global_mod import x
时,你在你的模块里创建了一个名字x
,它的值和global_mod
里的x
是一样的。对于函数和类来说,这样做是可以的,因为人们通常不会在后面重新给这些名字赋值。
正如Alex指出的,如果你使用import global_mod
,然后用global_mod.x
,你就能避免这个问题。你在模块里定义的名字会是global_mod
,它总是指向你想要的模块,然后通过属性访问来获取x
,就能得到x
的最新值。