为什么我无法在Python中更改其他模块的变量?

4 投票
2 回答
1776 浏览
提问于 2025-04-16 07:40

我正在尝试让第二个模块能够修改第一个模块的变量,但这似乎不太奏效。

我有两个问题:1) 为什么这样不行,从语言开发的角度来看,这背后的原因是什么? 2) 有没有什么简单的方法可以让我以稍微不同的方式做到这一点?

a.py:

import b

test1 = 'a'
test2 = None
test3 = '3'

if __name__ == '__main__':
  print test1, test2, test3 #prints 'a', None, 3
  b.changeVars()
  print test1, test2, test3 #prints 'a', None, 3 (i.e. nothing has changed)

b.py:

import a

def changeVars():
  print a.test1, a.test2, a.test3 #prints 'a', None, 3
  a.test1 = 'NEW VAR 1'
  a.test2 = 'NEW VAR 2'
  a.test3 = 'NEW VAR 3'

  print a.test1, a.test2, a.test3 #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'

2 个回答

0

做这种事情有个更好的方法,就是在你想要修改变量的模块里声明这些变量。在这个例子中,就是在 b 里。然后在 a 中导入 b,这样你就可以随心所欲地使用这些变量了。你可以像在 a 中声明的一样使用这些变量,也可以对它们进行修改。看看这个:

b.py

test1 = 'a'
test2 = None
test3 = '3'

def changeVars():
    global test1,test2,test3
    test1 = 'NEW VAR 1'
    test2 = 'NEW VAR 2'
    test3 = 'NEW VAR 3'

    print test1, test2, test3   #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'

a.py

import b

if __name__ == '__main__':
    print b.test1, b.test2, b.test3   #prints 'a', None, 3
    b.changeVars()
    print b.test1, b.test2, b.test3   #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'


注意:在这种情况下不需要循环导入;循环导入会导致你的问题,因为它的表现和你想象的不一样。所以,只需一个导入,你就能在代码中实现你想要的功能,并且可以在两个模块中修改这些变量的值。

9

发生的事情是,当 b.py 尝试 import a 时,sys.modules 中没有对应的条目,因为这个条目是在 __main__ 下。这导致导入机制重新导入这个模块,并将其放在 a 这个名字下。所以现在就有了一个 a 模块和一个完全不相关的 __main__ 模块。把 b.py 改成下面这样就能解决这个问题。

import sys
a = sys.modules['__main__']

def changeVars():
  print a.test1, a.test2, a.test3 #prints 'a', None, 3
  a.test1 = 'NEW VAR 1'
  a.test2 = 'NEW VAR 2'
  a.test3 = 'NEW VAR 3'

  print a.test1, a.test2, a.test3 #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'

这样做的结果是

aaron@aaron-laptop:~/code/tmp$ python a.py
a None 3
a None 3
NEW VAR 1 NEW VAR 2 NEW VAR 3
NEW VAR 1 NEW VAR 2 NEW VAR 3
aaron@aaron-laptop:~/code/tmp$ 

为了更好地理解发生了什么,可以考虑这些文件:

#a.py
import b
import a

test = 'Foo'   

if __name__ == '__main__':
  print test  #prints 'Foo'
  b.changeVars()
  print a.test, test # prints 'Foo', 'Bar'

#b.py
import a as a1

import sys
a2 = sys.modules['__main__']

def changeVars():

  print a1.test, a2.test # Prints 'Foo', 'Foo'
  a2.test = 'Bar'
  print a1.test, a2.test # Prints 'Foo', 'Bar'

这将输出

Foo
Foo Foo
Foo Bar
Foo Bar

这清楚地显示了 sys.modules['a']sys.modules['__main__'] 指向两个不同的对象。解决办法可能是在 a.py 的第一行加上以下内容

import __main__ as a  # due to Ignacio Vazquez-Abrams 

这样做可以让其他模块也能 import a。不过,总的来说,我真的不明白你为什么要这样做。可能还有更好的方法来完成这个任务。

撰写回答