一种方法是使用 import x,而不使用“from”关键字。因此,您可以在任何地方使用其名称空间来引用事物。
还有其他方法吗?喜欢在 C++ ifnotdef __b__ def __b__ 中做类似的事情吗?
一种方法是使用 import x,而不使用“from”关键字。因此,您可以在任何地方使用其名称空间来引用事物。
还有其他方法吗?喜欢在 C++ ifnotdef __b__ def __b__ 中做类似的事情吗?
将任何一对相互依赖的模块合并到一个模块中。然后引入额外的模块来恢复旧名称。
例如,
# 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
循环导入是一种“代码味道”,通常(但不总是)表明某些重构是合适的。例如,如果A.x
usesB.y
和B.y
uses A.z
,那么您可能会考虑移动A.z
到它自己的模块中。
如果您确实认为需要循环导入,那么我通常建议导入模块并引用具有完全限定名称的对象(即,import A
并使用A.x
而不是from A import x
)。
如果你想这样做from A import *
,答案很简单:不要那样做。您通常应该这样做import A
并引用限定名称。
对于 quick&dirty 脚本和交互式会话,这是完全合理的做法——但在这种情况下,您不会遇到循环导入。
import *
在某些情况下,在实际代码中执行是有意义的。例如,如果您想隐藏一个复杂的模块结构,或者您动态生成的模块结构,或者在版本之间频繁更改,或者如果您要包装其他人的包的嵌套太深,import *
那么“包装模块”可能是有意义的" 或顶级包模块。但在这种情况下,您导入的任何内容都不会导入您。
事实上,我很难想象在任何情况下import *
都有必要并且循环依赖甚至是可能的。
如果你正在做from A import foo
,有办法解决这个问题(例如,import A
then 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
为了实现方便,您可能需要确保指定 a以确保如果有人从交互式会话中对您__all__
执行操作,导入的名称不会出现在您的命名空间中。)import *
此外,正如其他人所指出的,大多数(但不是全部)循环依赖的情况是糟糕设计的征兆,以合理的方式重构您的模块将解决它。在极少数情况下,您确实需要将名称带入命名空间,并且一组循环模块实际上是最好的设计,一些人为重构可能仍然是比foo = A.foo
.