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

Python:在模块和类之间共享全局变量,python,scope,global-variables,module,Python,Scope,Global Variables,Module,我知道在Python中,可以跨模块共享一个全局变量。然而,我想知道这在多大程度上是可能的,以及为什么。比如说, 全局_mod.py x = None 中段通道模块 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__(s

我知道在Python中,可以跨模块共享一个全局变量。然而,我想知道这在多大程度上是可能的,以及为什么。比如说,

全局_mod.py

x = None
中段通道模块

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,也不会打印任何内容。为什么会这样?在mew()将x赋值到bot_modif_mod.py之前,似乎在mid_access_mod.py对x求值。

发生这种情况是因为您使用的是不可变的值(int和None),导入变量就像是按值传递,而不是按引用传递

如果您将global_mod.x制作成一个列表,并操纵它的第一个元素,它将如您所期望的那样工作

当您从global\u mod import x执行
操作时,您正在模块中创建一个名称
x
,其值与
global\u mod
中的
x
相同。对于函数和类之类的东西,这正如您所期望的那样有效,因为人们(通常)以后不会重新指定这些名称


正如Alex指出的,如果您使用
import global\u mod
,然后使用
global\u mod.x
,您将避免该问题。您在模块中定义的名称将是
global\u mod
,它总是指您想要的模块,然后使用属性访问获取
x
将从导入中获取
x

的最新值*
不是代码中使用的一个好习惯用法-它是专门用于,如果有的话,可以在交互式会话中作为保存某些键入内容的快捷方式。它基本上是在该时间点“快照”模块中的所有名称——如果您重新绑定其中任何一个名称,快照将变得过时,所有类型的问题都将随之发生。而这仅仅是你使用来自。。。导入*
构造


需要我的建议吗?忘记你曾经听说过的那个结构,永远不要再使用它。使用
import global\u mod as m
,然后始终使用限定的名称,例如
m.x
——限定的名称是,因此在Python中比单纯的单名更方便、更强大,这一点都不好笑。(import
语句的
as m
部分是完全可选的,基本上是为了简洁起见而存在的,或者有时是为了解决一些名称冲突的问题;当您觉得方便时使用它,因为它没有缺点,但当您觉得不必要时,不要强迫或甚至敦促您使用).

我修改了示例,将列表用于x,并按照顶部答案中的建议进行列表赋值(x[0]=…),打印返回相同的初始值(无)…这验证了“来自全局_mod import*”是一个副本,无论是否可变


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

如Ned Batchelder所述,只有值是共享的,而不是实际的对象。如果您想通过引用共享对象,那么您可能正在查看
线程本地数据

例如:

现在,无论何时您想要访问或更改变量g.population,只要它是您试图从中访问它的同一线程,您就会得到它的更新值


阅读Python文档中的更多内容:

要解决此问题,只需将
从全局\u mod import*
更改为
导入全局\u mod

新的mid_access_mod.py将是:

import global_mod

class delta:
    def __init__(self):
        print global_mod.x
原因是可以找到的

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


我认为你在这里的回答是误导性的。问题主要不是因为使用可变或不可变类型,而是使用modulename import*中的
而不是
import modulename
。如果你使用emish的代码并将global_mod.py更改为
x=['starting list']
然后将bot_modif_mod.py中的重新分配更改为
global_mod.x=['new list']
您会发现这会打印“['starting list']正如Alex Martinelli所说,真正的问题是modulename导入中的
*
快照。我希望其他用户不要像我一样困惑。我相信@Ned想说的是,考虑到
x=['starting list']
,人们应该通过执行
x[0]='new value'
来编辑值,而不是将值指定为一个全新的列表(
x=['new list']
import global_mod

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