【问题标题】:Python and Circular imports yet againPython 和循环导入再次
【发布时间】:2014-12-26 22:06:41
【问题描述】:

假设我有一个如下所示的模块:

circlejerking/
├── bar.py
├── foo.py
└── __init__.py

bar.py:

from .foo import Foo

class Bar(Foo):
    pass

foo.py:

from .bar import Bar

class Foo(object):
    my_bar = Bar()

__init__.py:

from .foo import Foo
from .bar import Bar

__all__ = [
    'Foo',
    'Bar'
]

由于循环导入,使用该模块失败。

In [1]: from circlejerking import Foo
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-1-2258014c7099> in <module>()
----> 1 from circlejerking import Foo

/home/me/circlejerking/__init__.py in <module>()
----> 1 from .foo import Foo
2 from .bar import Bar
3
4 __all__ = [
5 'Foo',

/home/me/circlejerking/foo.py in <module>()
----> 1 from .bar import Bar
2
3 class Foo(object):
4 my_bar = Bar()

/home/me/circlejerking/bar.py in <module>()
----> 1 from .foo import Foo
2
3 class Bar(Foo):
4 pass

ImportError: cannot import name Foo

我了解问题并且我知道,与 python 相关的循环导入问题已被多次讨论,但我似乎无法使其正常工作。 SO 对这个问题的两个 goto 答案是:

  1. 重新设计你的代码,你拿错了或者
  2. 仅在需要的地方导入其他模块。

我相当肯定,我的设计还可以,是的,我确信这两个类实际上不是一回事。

将另一个类导入其他地方不是一种选择,因为我需要它们就在它们所在的地方。

有什么想法吗?

【问题讨论】:

  • 也许将所有导入移动到__init__?这样您的进口订单就可以一劳永逸地解决
  • 应该是class Bar(Foo) 吗?现在你根本没有任何东西叫Bar。另外,你为什么要那样“需要”它?
  • 你的问题比循环导入更糟糕;你的类实际上有循环references,这在Python 中无法真正解决,即使两者都定义在同一个文件中。见this question。您确定需要 my_bar 成为类属性而不是实例属性吗?
  • @BrenBarn 嗯..你可能是对的,我实际上想要一个实例属性并且只是坚持这个想法。让我检查一下。
  • 在这种情况下,您可能需要this question

标签: python import circular-dependency


【解决方案1】:

一般来说,你可以通过注入模式来解决这个问题:

这个模块是好的:

from .foo import Foo
class Bar(Foo):
    pass

然后你的其他模块变成:

class Foo(object):
    bar = None

    @classmethod
    def set_bar(cls, bar):
        cls.bar = bar

然后由任何使用 Foo 的东西来确保在使用 set_bar 之前正确调用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 2014-04-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2012-10-13
    • 2013-06-29
    相关资源
    最近更新 更多