递归导入语句

JP骑士

我在包中涉及到递归导入语句的问题。我看到了很多关于该主题的文章,但找不到有效的解决方案。我转载了一个非常小的示例来解决我的问题。

软件包中的文件组织temp如下:

|-- __init__.py
|-- abstract.py
|-- a.py
|-- b.py

该文件__init__.py包含

from .a import A
from .b import B

该文件abstract.py包含

from abc import ABC, abstractmethod

class Abstract(ABC):

    @abstractmethod
    def __init__(self):
        pass

该文件a.py包含

from .abstract import Abstract
from .b import B

class A(Abstract):

    def __init__(self, string):
        super().__init__()
        self.string = string

    def as_b(self):
        return B(int(self.string))

该文件b.py包含

from .abstract import Abstract
from .a import A

class B(Abstract):

    def __init__(self, integer):
        super().__init__()
        self.integer = integer

    def as_a(self):
        return A(str(self.integer))

然后,我创建了一个文件foo.py来测试temp包含以下内容软件包

from temp import A, B

an_a = A("2")
a_b = B(4)

an_a_as_b = A.as_b()
a_b_as_a = B.as_a()

在运行时,我收到错误消息ImportError: cannot import name 'A'我的理解是,这是由于递归导入语句(类A导入类B,反之亦然)引起的。

什么是实现类的最佳Python的方式A,并Btemp包?

内森(NathanVērzemnieks)

除了合并文件以外,还有几种选择,您说过,您的工作场所惯例不建议使用。(下面的选项适用于来自Sanyash的此评论中链接的答案的Python 3 relative 。我认为在此处包括答案是有道理的,因为该问题并不直接与相对导入有关。)

将循环导入移动到文件末尾

该文件a.py变为:

from .abstract import Abstract

class A(Abstract):
    # ...

from .b import B

b.py以相同的方式进行更改。这是一个简单的更改,但缺点是您的进口分散。有人可能会通过将导入移到顶部来“清理”您的代码,并遇到同样的困惑。(您可以发表评论,但是人们经常会错过评论。)

导入模块而不是类

您还可以让每个模块导入另一个模块,而不是从另一个模块导入。a.py变成:

from .abstract import Abstract
from . import b

class A(Abstract):
    # ...
    def as_b(self):
        return b.B(int(self.string)) # note the change to use b.B

当然b.py也会发生类似的变化 这使我成为最干净的解决方案-我极力主张尽可能将进口货物保持在一起。(我认为这种方法没有任何缺点,但是如果有人知道任何方法,请发表评论,我将对此进行更新。)

将导入内容移至使用位置

如果你只是指Ba.py一个地方这样您可以将导入到需要的地方的功能:

from .abstract import Abstract

class A(Abstract):
    # ...

    def as_b(self):
        from .b import B
        return B(int(self.string))

和相同b.py与第一个选项相比,它具有一个优势,即可以更轻松地了解为什么导入不在顶部,并且我认为它不太可能导致混乱或错误。但是,它可以掩盖导入错误,所以我认为这不是理想的选择。而且,首次调用as_a会稍微减慢速度as_b,因为导入将在第一次调用每个函数时发生,并且需要非零时间。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章