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

时间:2010-07-26 19:30:28

标签: python scope global-variables module

我知道可以在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()

即使所有模块共享全局变量x,也会打印无。为什么会这样?似乎x在mid_access_mod.py中被评估,然后由mew()在bot_modif_mod.py中赋值。

5 个答案:

答案 0 :(得分:38)

这是因为您使用的是不可变值(int和None),导入变量就像按值传递,而不是通过引用传递。

如果你使global_mod.x成为一个列表并操纵它的第一个元素,那么它将按你的预期工作。

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

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

答案 1 :(得分:26)

from whatever import * 不是在您的代码中使用的好习惯用语 - 如果有的话,它可以在交互式会话中用作保存某些输入的快捷方式。它基本上“快照”了当时模块中的所有名称 - 如果您重新绑定任何这些名称,快照将变得陈旧,随之而来的是所有类型的问题。而这只是你通过使用可怜的from ... import *构造注册的无法解决的混乱的开始。

需要我的建议吗?忘记你曾经听说过现有的构造,永远不会再使用它。使用import global_mod as m并始终使用其他符合条件的名称,例如m.x - 合格的名称如此在Python中更加方便和强大,而不仅仅是裸名,它甚至都不好笑。 (as m语句的import部分是完全可选的,基本上是为了简洁目的而存在,或者有时是为了解决名称冲突的一些问题;如果你觉得它很方便,可以使用它,因为它有没有缺点,但如果你认为没必要的话,不要强迫甚至不要使用。)

答案 2 :(得分:0)

我修改了示例以使用x的列表,并按照最高回答中的建议列出了分配(x [0] = ..),并且print返回了相同的初始值(None)。这验证了“来自global_mod import *”是一个副本,无论是否可变。

根据评论“import global_mod”的建议,如果“print global_mod.x =然后在mid_access_mod中使用。

答案 3 :(得分:0)

正如Ned Batchelder所提到的,只有值是共享的,而不是实际的对象。如果您想通过引用共享对象,那么您可能正在查找Thread-Local Data

例如:

import threading

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

现在,每当您想要访问或更改变量g.population时,您将获得它的更新值,前提是它与您尝试访问它的线程相同。

阅读Python文档:https://docs.python.org/3/library/threading.html#thread-local-data

答案 4 :(得分:0)

要解决此问题,只需将from global_mod import *更改为import global_mod

新的 mid_access_mod.py 将是:

import global_mod

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

可以找到here的原因。

  

由于引用和名称绑定在Python中的工作方式,如果你想更新模块中的一些符号,比如foo.bar,从该模块外部更新,并让其他导入代码“看到”更改,你必须以某种方式导入foo。

相关问题