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