提问人:Luc Hayward 提问时间:11/10/2023 更新时间:11/10/2023 访问量:35
跨不同 Python 模块访问列表时的行为不一致
Inconsistent Behavior of a List When Accessed Across Different Python Modules
问:
我在 Python 中遇到了一个特殊的问题,该列表在跨不同模块访问时似乎表现不一致。我有三个 Python 文件:main.py、mymodule.py 和 myothermodule.py。列表 main.py 中定义,mymodule.py 中修改。但是,当我从不同的模块打印时,它显示不同的内容。从内部 main.py 变量的副本与我在其他模块中使用时访问它时不同。mylist
mylist
mylist
main.mylist
下面是一个最小的工作示例:main.py
import mymodule
import myothermodule
mylist = []
def run():
print("In main func")
mymodule.bar()
print(f"In run {mylist=}")
if __name__ == '__main__':
print("In main guard")
run()
print(f"In main guard again {mylist=}")
myothermodule.foo()
mymodule.py
import main
def bar():
print("In bar() appending to main.mylist")
main.mylist.append(1)
print(f"{main.mylist=}")
myothermodule.py
import main
def foo():
print(f"In myothermodule.foo() {main.mylist=}")
当我运行 main.py 时,我得到以下输出:
In main guard
In main func
In bar() appending to main.mylist
main.mylist=[1]
In run mylist=[]
In main guard again mylist=[]
In myothermodule.foo() main.mylist=[1]
预期输出为:
In main guard
In main func
In bar() appending to main.mylist
main.mylist=[1]
In run mylist=[1]
In main guard again mylist=[1]
In myothermodule.foo() main.mylist=[1]
如您所见,在 main.py 中访问时未更新mylist
答:
您遇到的问题是在 Python 中处理全局变量和导入时的常见问题。由于 Python 处理模块导入的方式和全局变量的定义,出现了这个问题。
在您的设置中,导入 和 ,这两个模块都导入 .此循环导入在 和 中创建模块的单独实例。因此,in 和 与 .main.py
mymodule.py
myothermodule.py
main.py
main
mymodule
myothermodule
mylist
mymodule
myothermodule
mylist
main.py
当追加到 时,它会在自己的实例中修改 ,而不是原始脚本中的实例。同样,正在访问其自己的实例。mymodule.bar()
main.mylist
mylist
main
main.py
myothermodule.foo()
mylist
main
若要解决此问题,可以重构代码以避免循环导入,并以不同的方式使用共享状态。一种常见的方法是将参数传递给其他模块中的函数,而不是导入到这些模块中。以下是修改代码的方法:mylist
main.py
main.py:
import mymodule
import myothermodule
mylist = []
def run():
print("In main func")
mymodule.bar(mylist)
print(f"In run {mylist=}")
if __name__ == '__main__':
print("In main guard")
run()
print(f"In main guard again {mylist=}")
myothermodule.foo(mylist)
mymodule.py:
def bar(mylist):
print("In bar() appending to mylist")
mylist.append(1)
print(f"{mylist=}")
myothermodule.py:
def foo(mylist):
print(f"In myothermodule.foo() {mylist=}")
通过这些更改,将显式传递给其他模块中的函数,从而确保对同一列表实例进行所有修改。这种方法避免了循环导入,并确保了不同模块之间状态的一致性。mylist
mylist
评论
__main__
main.py
__main__
mymodule
myothermodule
main
mylist
main.py
main.py
mymodule.py
anothermodule.py
main
mymodule
anothermodule
__main__
mylist
__main__