假设您有以下模块:
foo.py:
<span class="kn">from</span> <span class="nn">bar</span> <span class="kn">import</span> <span class="n">bar_var</span>
<span class="n">foo_var</span> <span class="o">=</span> <span class="mi">1</span>
www#gaodaima.com来源gaodaima#com搞(代@码网搞代码
bar.py:
<span class="kn">from</span> <span class="nn">foo</span> <span class="kn">import</span> <span class="n">foo_var</span>
<span class="n">bar_var</span> <span class="o">=</span> <span class="mi">2</span>
问题是解释器将执行以下步骤:
-
首先导入foo
-
创建用于foo的空全局变量
-
foo被编译并开始执行
-
foo 导入 bar
-
创建了用于bar 的空全局变量
-
bar被编译并开始执行
-
bar导入foo(这是一个空操作(no-op ),因为已经有一个名为foo的模块)
-
bar.foo_var = foo.foo_var
最后一步失败了,因为Python还没有解释foo,而foo的全局符号字典仍然是空的。
当你使用 import foo
,然后尝试在全局代码中访问 foo.foo_var
时,会发生同样的事情。
这个问题有(至少)三种可能的解决方法。
Guido van Rossum 建议避免使用 from <module> import ...
,并将所有代码放在函数中。全局变量和类变量的初始化只能使用常量或内置函数。这意味着导入模块中的所有内容都被引用为 <module>.<name>
。
Jim Roskind建议在每个模块中按以下顺序执行步骤:
-
导出(全局变量,函数和不需要导入基类的类)
-
导入
声明 -
活动代码(包括从导入值初始化的全局变量)。
van Rossum不喜欢这种方法,因为导入出现在一个陌生的地方,但这种方法确实有效。
Matthias Urlichs建议重构代码,以便首先不需要递归导入。
这些解决方案并不相互排斥。
来源:搞代码网:原文地址:https://www.gaodaima.com