python循环导入文件_Python循环导入?

要理解循环依赖关系,您需要记住Python本质上是一种脚本语言。方法外部语句的执行在编译时发生。导入语句就像方法调用一样执行,要理解它们,您应该像方法调用一样考虑它们。

当您进行导入时,所发生的事情取决于您要导入的文件是否已经存在于模块表中。如果使用,Python将使用符号表中当前的任何内容。否则,Python将开始读取模块文件,编译/执行/导入它在那里找到的任何内容。编译时引用的符号是否被找到,取决于它们是否已经被看到,或者编译器还没有看到它们。

假设您有两个源文件:

文件X.pydef X1:

return "x1"from Y import Y2def X2:

return "x2"

文件Y.pydef Y1:

return "y1"from X import X1def Y2:

return "y2"

现在假设您编译了X.py文件。编译器首先定义X1方法,然后点击X.py中的import语句。这导致编译器暂停X.py的编译并开始编译Y.py。此后不久,编译器将命中Y.py中的import语句。由于X.py已经在模块表中,Python使用现有的不完整X.py符号表来满足任何请求的引用。在X.py中的import语句之前出现的任何符号现在都在符号表中,但是后面的任何符号都不是。因为X1现在出现在IMPORT语句之前,所以它已成功导入。然后Python继续编译Y.py。在这样做时,它定义了Y2并完成了对Y.py的编译。然后继续编译X.py,并在Y.py符号表中找到Y2。编译最终完成w/o错误。

如果尝试从命令行编译Y.py,则会发生非常不同的情况。在编译Y.py时,编译器在定义Y2之前点击import语句。然后开始编译X.py。很快,它就会命中X.py中的import语句,该语句需要Y2。但是Y2没有定义,所以编译失败。

请注意,如果您修改X.py以导入Y1,编译将始终成功,无论您编译的是哪个文件。但是,如果您修改文件Y.py以导入符号X2,则两个文件都不会编译。

当模块X或X导入的任何模块可能导入当前模块时,请不要使用:from X import Y

当您认为可能存在循环导入时,您也应该避免编译时引用其他模块中的变量。考虑一下看似无辜的代码:import X

z = X.Y

假设模块X在这个模块导入X之前导入这个模块。进一步假设Y是在导入语句之后在X中定义的。在导入该模块时,将不会定义Y,您将得到一个编译错误。如果这个模块首先导入Y,您就可以逃脱它。但是,当您的一个同事无意地更改了第三个模块中定义的顺序时,代码就会中断。

在某些情况下,您可以通过将导入语句向下移到其他模块所需的符号定义下面来解决循环依赖关系。在上面的例子中,导入语句之前的定义永远不会失败。导入语句后的定义有时会失败,这取决于编译的顺序。您甚至可以将导入语句放在文件的末尾,只要编译时不需要导入的符号。

请注意,在模块中向下移动导入语句会掩盖您正在做的事情。在模块顶部加上一个注释来弥补这一点,如下所示:#import X   (actual import moved down to avoid circular dependency)

一般来说,这是一个不好的做法,但有时是很难避免的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值