8

一种方法是使用 import x,而不使用“from”关键字。因此,您可以在任何地方使用其名称空间来引用事物。

还有其他方法吗?喜欢在 C++ ifnotdef __b__ def __b__ 中做类似的事情吗?

4

3 回答 3

11

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

例如,

# 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
于 2012-12-13T20:13:38.030 回答
5

循环导入是一种“代码味道”,通常(但不总是)表明某些重构是合适的。例如,如果A.xusesB.yB.yuses A.z,那么您可能会考虑移动A.z到它自己的模块中。

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

于 2012-12-13T20:20:29.410 回答
1

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

对于 quick&dirty 脚本和交互式会话,这是完全合理的做法——但在这种情况下,您不会遇到循环导入。

import *在某些情况下,在实际代码中执行是有意义的。例如,如果您想隐藏一个复杂的模块结构,或者您动态生成的模块结构,或者在版本之间频繁更改,或者如果您要包装其他人的包的嵌套太深,import *那么“包装模块”可能是有意义的" 或顶级包模块。但在这种情况下,您导入的任何内容都不会导入您。

事实上,我很难想象在任何情况下import *都有必要并且循环依赖甚至是可能的。

如果你正在做from A import foo,有办法解决这个问题(例如,import Athen 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.

于 2012-12-13T20:33:35.817 回答