2012-12-13 99 views
7

一种方法是使用import x,而不使用“from”关键字。那么你可以在任何地方用名称空间来引用它们。在Python中避免循环(循环)导入?

有没有其他办法?像在C++中做的事情ifnotdef __b__ def __b__类型的东西?

+2

没有循环依赖关系,通过组合y的x和y的依赖关系来创建z – Esailija

+0

这篇文章是重复的:http://stackoverflow.com/questions/744373/circular-or-cyclic -imports-in-python – alinsoar

+1

@alinsoar这不是一个完全重复的问题 - 当你有循环导入时会发生什么?这个问题要求技术来避免它们。 –

回答

10

将任何一对互相依赖的模块合并到一个模块中。然后引入额外的模块以恢复旧名称。

例如,

# a.py 
from b import B 

class A: whatever 

# b.py 
from a import A 

class B: whatever 

成为

# common.py 
class A: whatever 
class B: whatever 

# a.py 
from common import A 

# b.py 
from common import B 
+0

我认为你的意思是从'普通进口A'和'从普通进口B''做'? – jdi

+0

@jdi:是的。谢谢,修复它。 –

+21

这迫使人们开始在'common.py'中声明所有内容,而不是'a.py'和'b.py'。恕我直言,不是一个好的解决方 – Nick

5

圆形进口是一个 “代码味道”,和经常(但不总是)表明一些重构将是适当的。例如,如果A.x使用B.yB.y使用A.z,那么你可以考虑将A.z移动到它自己的模块中。

如果您认为需要循环导入,那么我通常会建议导入模块并引用具有完全限定名称的对象(即import A和使用A.x而不是from A import x)。

+1

如果你正在进行一些明确的类型检查,该怎么办?我现在正在尝试这样做,所以我可以提供非常详细的错误消息,而不是我的客户不理解的一些令人迷惑的追踪。 – Nick

0

如果您想要做from A import *,答案很简单:不要这样做。你通常假设import A并引用限定名称。

对于快速&脏脚本和交互式会话,这是一件非常合理的事情 - 但在这种情况下,您将不会遇到循环导入。

在某些情况下,在实际代码中执行import *是有意义的。例如,如果你想隐藏一个复杂的模块结构,或者动态生成的模块结构,或者在不同版本间频繁变化,或者你要包装的嵌套层次太深的其他软件包,import *可能从“包装器模块“或顶级封装模块。但在这种情况下,您导入的任何东西都不会导入您。

事实上,我很难想象任何情况下import *是保证和循环依赖甚至是可能性。

如果你在做from A import foo,那么有办法(例如,import A然后foo = A.foo)。但你可能不想这样做。再次考虑您是否真的需要将foo加入您的名称空间 - 限定名称是一项功能,而不是需要解决的问题。

如果你正在做的只是from A import foo为了方便实现你的功能,因为A实际上是long_package_name.really_long_module_name和你的代码是因为所有这些调用long_package_name.really_long_module_name.long_class_name.class_method_that_puts_me_over_80_characters的不可读,请记住,你总是可以import long_package_name.really_long_module_name as P,然后使用P你合格调用。

(另外请记住,与实施方便做任何from,你可能希望确保指定__all__以确保进口的名字不,如果有人对你做一个import *似乎是你的命名空间的一部分来自互动式会议。)

另外,正如其他人指出的那样,大多数(但不是全部)循环依赖的情况是设计不良的一个症状,并且以合理的方式重构模块将会修复它。在极少数情况下,您确实需要将名称带入名称空间,并且一组循环的模块实际上是最好的设计,但某些人工重构可能仍然是比foo = A.foo更好的选择。