【问题标题】:Import trouble in python在python中导入麻烦
【发布时间】:2012-09-24 20:51:48
【问题描述】:

想象一下下面的项目结构

app/
    foo/
        __init__.py
        a.py
        b.py

a.py 我有类 A 它使用 b.py 文件中的类 B,并且b.py 中的 B 类使用 A 类形式 a.py

如果我写:

from foo.b import B 

a.py

from foo.a import A

b.py中,递归发生

如何正确导入,而不将 AB 合并到单个文件中

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    Python 不支持循环导入,部分原因是它们通常是设计缺陷的征兆。

    您可以做的是使AB 自包含并从第三个文件中引用它们,或者,将共享结构提取到第三个文件中并从您的两个模块中引用。这将如何发挥作用取决于AB 是什么以及您认为它们应该相互了解的原因。

    例如,您可以使 A 仅通过其构造函数引用 B 的实例,这样您就不需要导入:

    class A(object):
        def __init__(self, b):
            self.b = b
        # .. some methods that reference self.b
    

    如果涉及到继承,它会变得有点复杂。在这种情况下,您可能不希望超类知道子类,因为这会违反 substitution principle

    【讨论】:

    • 我有类似树结构的东西。例如 A - 是根元素,B 是它的子元素(子元素是 B 的实例)所以 A 对象必须知道他的子元素,而子元素现在必须知道他的子元素。
    • @atom:这没什么用。在层次结构中,父级通常不需要知道其确切子级的类型。在其他编程语言中,您将使用抽象类或接口来构建类型结构。在 Python 中,首选的方法是只使用鸭子类型。
    • @Rohit:我希望剩下的答案比这个流行词更有帮助
    • @atom:你应该阅读abstract factory pattern,它可以用来避免这种紧密耦合。我在您的描述中看不到为什么DbAuthor 需要创建DbPost 的引用,因此不需要导入DbPost。但一般来说,您根本不应该通过调用构造函数来创建数据对象的实例!您应该有一个专用的数据存储对象,它充当创建对象(或从数据库中获取它们并创建包装器)的工厂。看看 sqlalchemy 或者其他 ORM 系统就行了
    • @atomAltera:不,他们现在不需要工厂的类型,只需要它的接口(这是隐含的,因为 Python 有鸭子类型)。特别是,他们不需要创建工厂的实例。他们通过其构造函数(或通过依赖注入等)获得对工厂的引用。
    猜你喜欢
    • 2017-04-10
    • 2011-01-18
    • 2012-08-23
    • 2014-06-28
    • 2018-10-29
    • 1970-01-01
    • 2019-09-17
    • 2020-12-23
    • 2023-02-05
    相关资源
    最近更新 更多