Python 在这种情况下,为什么循环导入会导致问题?

Python 在这种情况下,为什么循环导入会导致问题?,python,import,cyclic,Python,Import,Cyclic,我理解第一部分 问题是当您从foo导入abc和从bar导入xyz时。因为现在每个模块都要求在导入之前已经导入另一个模块(因此我们导入的名称存在) 为什么答案说它会导致问题?当模块像任何对象一样加载时,它分两个阶段完成。首先,分配内存并创建最外层的数据结构(目前我们可以将其视为名称空间)。然后,里面的东西依次初始化 bar.py中类似于import foo的语句在当前名称空间中指定名称foo,并将其指向数据结构sys.modules['foo']。即使该对象还没有被初始化,这也会起作用,因为它至少

我理解第一部分

问题是当您从foo导入abc和从bar导入xyz时。因为现在每个模块都要求在导入之前已经导入另一个模块(因此我们导入的名称存在)


为什么答案说它会导致问题?

当模块像任何对象一样加载时,它分两个阶段完成。首先,分配内存并创建最外层的数据结构(目前我们可以将其视为名称空间)。然后,里面的东西依次初始化

bar.py
中类似于
import foo
的语句在当前名称空间中指定名称
foo
,并将其指向数据结构
sys.modules['foo']
。即使该对象还没有被初始化,这也会起作用,因为它至少已经被创建,并且在任何东西有机会调用它之前,它就已经被初始化了

如果
foo
包含语句
import bar
,那么解释器所要做的就是将当前部分初始化的
bar
模块分配给
foo
命名空间中的名称
bar
。同样,当任何东西尝试使用它时,
foo
应该完全初始化


当您尝试循环导入特定名称时,问题会更大,因为您只能从已初始化的模块导入特定名称

假设您在
bar.py
中有来自foo import baz的
,在
foo.py
中有来自bar import qux的
。解释器尝试完全加载
foo
,因此它可以确定哪个对象是
baz
,但要做到这一点,它需要
qux
。但要获得
qux
,它需要完全加载
bar
,这样它就可以知道什么是对象
qux
。但要做到这一点,它需要完全加载
foo
,以此类推。这将导致一个循环



这样做的最终结果是,您可以循环导入整个模块,因为解释器可以灵活地按顺序加载各自的内容,并且可以在调用模块之前可靠地初始化所有内容。但是您不能循环地从模块导入对象,因为解释器需要加载整个模块,然后才能确定您想要什么对象。解释此订购背后的技术流程。

请将此问题独立出来。“这种情况”的含义不太清楚。“为什么答案说它会导致问题?”-因为它描述了循环导入所产生的问题。@mkrieger1这是我不理解的。请写一个答案来解释。我想我写不出任何你链接的问题的答案中没有提到的东西。@mkrieger1好的,请在评论中向我解释。首先,感谢你的回答。假设,
a.py
包含
import b
b.py
包含
import a
——由于模块中的
import
语句只执行一次,因此该操作正常。为什么它不在您显示的另一个导入变量中只执行一次-
来自foo import baz
?使用您给出的两个示例:在第一个示例中,解释器实际上没有对
a
执行任何操作-它只是在
系统模块中找到它的条目并分配它,不管它是否已经完全初始化(它可以稍后完成)。在第二种情况下,解释器必须返回并完成初始化
foo
,以便找到
baz
应该引用的内容,这导致了问题(因为
foo
需要从
bar
等处获取内容)。因此在第二种情况下,
sys.modules
中没有条目,对吗?在第二种情况下,有,但还不够,因为尽管
sys.modules
包含
foo
foo
还不包含
baz
在sys.modules
中的'foo'应该可以工作,或者在sys.modules.values()中的
foo应该可以工作<代码>系统模块
是一种普通指令。