提问人:John Elion 提问时间:10/9/2023 最后编辑:John Elion 更新时间:10/9/2023 访问量:118
共享模块中的 Python 全局变量 [duplicate]
Python global variables in shared modules [duplicate]
问:
我正在尝试了解跨模块共享的变量的行为。我的印象是,一个模块中的全局变量可以在另一个模块中访问,有时这似乎是发生的事情,但有时并非如此。 (我承认全局变量通常不是正确的工具,但在某些情况下,它们的使用是合适的。
下面是一个代码示例来说明我的困惑:
shared.py
globalvar=0 # a global scalar variable
globalarray1=[1,2,3] # a global array modified by .append()
globalarray2=['A','B','C'] # a global array modified by reassignment
def set_globals():
global globalvar
global globalarray1
global globalarray2
globalvar=1
globalarray1.append(4)
globalarray2=['a','b','c']
print("set_globals: globalvar="+str(globalvar))
print("set_globals: globalarray1="+str(globalarray1))
print("set_globals: globalarray2="+str(globalarray2))
module.py
from paas.shared import *
def _main_():
global globalvar
global globalarray1
global globalarray2
set_globals()
print("main: globalvar="+str(globalvar))
print("main: globalarray1="+str(globalarray1))
print("main: globalarray2="+str(globalarray2))
_main_()
当我运行程序时,我得到以下输出:
set_globals: globalvar=1
set_globals: globalarray1=[1, 2, 3, 4]
set_globals: globalarray2=['a', 'b', 'c']
main: globalvar=0
main: globalarray1=[1, 2, 3, 4]
main: globalarray2=['A', 'B', 'C']
所以
- 'main' 没有看到共享模块中由 'set_globals' 方法设置的相同标量变量 'globalvar'(赋值 'takek' 并在 'set_globals' 中打印,但 'main' 正在打印其他内容。
- 它似乎确实看到了相同的“globalarray1”——当 'main' 打印时,可以识别在 set_globals 中修改 globalarray1 的 append(4)。
- 它没有看到相同的“globalarray2”——set_globals 中分配的变量由 'set_globals' 正确打印,但 'main' 正在打印分配给 globalarray2 的原始值。
有人可以解释一下发生了什么吗?我只看过关于全局变量的相当简单的教程类型文档;如果有描述这里发生的事情的文档,我将不胜感激。
补充说明:这与函数中的局部变量隐藏同名全局变量的方式无关;这是两个不同的变量,具有相同的名称和不同的初始值。导入似乎确实创建了一个具有相同名称的新模块变量,但它以导入模块中同名变量的初始值开头。
答:
-1赞
memyself
10/9/2023
#1
你所观察到的源于 Python 在变量、导入和可变性方面的行为。让我们分解一下:
- 共享可变对象(在本例中为列表):
globalarray1
是一个列表,在 Python 中是一个可变对象。当您这样做时,您正在更改原始列表对象。globalarray1.append(4)
- 导入 using 时,您正在导入对该列表对象的引用。因此,当您在 中对列表进行突变时,该突变在 module.py 中可见。
globalarray1
module.py
from paas.shared import *
shared.py
- 重新分配变量:
globalarray2=['a','b','c']
Inside 将变量重新分配给新的 List 对象。但是,仍然引用原始列表对象。set_globals
module.py
- 对于标量,当您设置 时,您将修改 范围内变量的值。但是,在 中,仍然引用旧值 (0)。
globalvar
globalvar=1
set_globals
shared.py
module.py
globalvar
- Python 的导入机制:
- 当您使用语法时,您将从 into 中导入名称。如果稍后重新绑定其中一个名称(如使用 和 ),则绑定 in 保持不变。
from paas.shared import *
shared.py
module.py
shared.py
globalvar
globalarray2
module.py
如何解决此问题并查看一致的行为:
您应该使用显式模块前缀从共享模块访问变量。这样,您始终引用共享模块中变量的最新值。以下是如何更改您的,我们称之为:module.py
module2.py
import paas.shared as shared
def _main_():
shared.set_globals()
print("main: globalvar="+str(shared.globalvar))
print("main: globalarray1="+str(shared.globalarray1))
print("main: globalarray2="+str(shared.globalarray2))
_main_()
通过此更改,中的 print 语句将直接引用共享模块的变量版本,并且您将看到 和 之间的行为一致。_main_()
set_globals
_main_()
现在让我们比较一下输出。这是(从上面未修改):module.py
$ python module.py
set_globals: globalvar=1
set_globals: globalarray1=[1, 2, 3, 4]
set_globals: globalarray2=['a', 'b', 'c']
main: globalvar=0
main: globalarray1=[1, 2, 3, 4]
main: globalarray2=['A', 'B', 'C']
现在使用显式导入的新代码():module2.py
$ python module2.py
set_globals: globalvar=1
set_globals: globalarray1=[1, 2, 3, 4]
set_globals: globalarray2=['a', 'b', 'c']
main: globalvar=1
main: globalarray1=[1, 2, 3, 4]
main: globalarray2=['a', 'b', 'c']
评论
2赞
slothrop
10/9/2023
stackoverflow.com/help/gpt-policy
0赞
John Elion
10/9/2023
这似乎确实描述了我所看到的。我将探索在 import 语句上使用句柄;如果这可行,我认为这是一个非常完整的答案。
0赞
memyself
10/9/2023
运行修改后的 module.py 时看到的输出是什么?
0赞
John Elion
10/10/2023
这是有效的。
评论
from module import var
var
module
x = 5; y = x; x = 6
x = [1, 2, 3]; y = x; x.append(4)