You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python模块间共享全局变量的行为差异及原因咨询

跨模块共享变量的行为困惑

我正试图理解跨模块共享变量的行为。原本以为一个模块中的全局变量可以被另一个模块访问,有时确实如此,但有时却并非如此。(我知道全局变量通常不是合适的工具,但存在一些适合使用它们的场景。)

以下是代码示例:

shared.py

globalvar=0                 # 全局标量变量
globalarray1=[1,2,3]        # 通过.append()修改的全局数组
globalarray2=['A','B','C']  # 通过重新赋值修改的全局数组

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_函数无法看到shared模块中set_globals修改后的标量变量globalvar(修改在set_globals内生效并打印,但_main_打印的是原值)。
  • _main_能看到同一个globalarray1——set_globals中对globalarray1执行的append(4)操作,在_main_打印时能被识别。
  • _main_无法看到同一个globalarray2——set_globals中赋值后的globalarray2在该函数内打印正确,但_main_打印的是初始值。

补充说明:这与函数内局部变量隐藏同名全局变量的情况无关;这是两个同名但初始值不同的变量。看起来import操作创建了一个同名的新模块变量,其初始值来自导入模块中的同名变量。

有人能解释这是怎么回事吗?我只看过关于全局变量的基础教程类文档,如果有能解释此现象的文档,恳请提供相关指引。


解释

核心原因在于Python中变量赋值与可变对象修改的区别,以及from module import *的导入机制:

  1. from paas.shared import *的本质
    这种导入方式会把shared模块中所有非下划线开头的变量,复制一份到当前module.py的命名空间中。也就是说,module.py里的globalvar、globalarray1、globalarray2,一开始是shared模块对应变量的副本:

    • 对于不可变类型(如整数globalvar):副本是独立的数值,和原模块的变量指向不同的内存地址。
    • 对于可变类型(如列表globalarray1、globalarray2):副本是指向同一个列表对象的引用,此时两个模块的变量共享同一个内存中的列表。
  2. 不同操作的影响

    • 不可变类型(globalvar):set_globals里的globalvar=1是给shared模块的globalvar重新赋值,指向了新的整数对象。但module.py里的globalvar还是原来的副本(指向0),所以看不到修改。
    • 可变类型的原地修改(globalarray1.append(4)):append是对列表对象本身进行修改,没有改变变量的引用指向。因为module.py和shared的globalarray1指向同一个列表,所以修改会被两边同时看到。
    • 可变类型的重新赋值(globalarray2=['a','b','c']):这是给shared模块的globalarray2重新指向了一个新的列表对象。而module.py里的globalarray2还是指向原来的['A','B','C']列表,所以看不到新的赋值。
  3. 解决方法
    如果想让module.py能看到shared模块中变量的所有修改,应该直接导入模块本身,而不是导入变量:

    # module.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_()
    

    这样所有访问都是直接操作shared模块的命名空间,就能看到所有修改了。


内容的提问来源于stack exchange,提问作者John Elion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 03:00:07