Python 包含成员函数的循环依赖

Python circular dependency with the inclusion of member functions

当我尝试将现有函数作为成员函数合并到 class 中时,问题就出现了。我有一个类似于这样的设置:

类:

base(object)
    primitive(base)
        square(primitive)
        union(primitive)

我有一个名为 union 的函数,用户将其称为 returns 一个 union 原始对象。

obj1 = square()
obj2 = square()
obj3 = union(obj1, obj2) #this is the union function which returns a union primitive

我希望用户也能做到这一点

obj3 = obj1.union(obj2)

这就是问题所在。 primitive class 需要导入 union 函数,进而导入 union class,进而导入 primitive class,而我运行陷入循环依赖错误。有没有一种聪明的方法来重构代码或更改导入语句以允许它工作?

编辑:

为清楚起见,代码的结构如下:

operations/union.py(函数)

from objects import union as _union #the union class
def union(obj1, obj2): #the union function
    #CODE
    return _union(args)

objects/union.py (class)

from objects import primitive
class union(primitive):
    #CODE

objects/primitive.py

from operations import union #the function
class primitive(base):
    #CODE
    def union(self, obj2):
        return union(self, obj2)

有一个叫做union的class,它是一个包含联合输入对象信息的对象。用户不与之交互。然后是用户可以调用的 union 函数,其中 returns 一个 union 对象。我希望 primitive class 包含一个名为 union 的成员函数,它使用我已经编写的 union 函数。问题是 union 函数 returns 一个继承自 primitive class 的 union 对象。这会导致循环依赖问题。我可以删除 union 成员函数,但用户不能这样做

obj3 = obj1.union(obj2)

听起来您将 primitivesquare 定义在单独的 modules/files 中给自己带来了很多麻烦。如果您在同一个模块中定义它们,我怀疑您会遇到任何麻烦。例如,以下工作正常:

class Primitive:
    pass

class Square(Primitive):
    def union(self, other):
        return Union(self, other)

class Union(Primitive):
    def __init__(self, *members):
        self.members = members

obj1 = Square()
obj2 = Square()
obj3 = obj1.union(obj2)

print(type(obj3))
print(obj3.members)

如果您坚持将 类 放在不同的文件中,您可以这样做:

primitive.py:

    class Primitive:
        pass

square.py:

    from .primitive import Primitive

    class Square(Primitive):
        def union(self, other):
            from .union import Union
            return Union(self, other)

union.py:

    from .primitive import Primitive

    class Union(Primitive):
        def __init__(self, *members):
            self.members = members

test.py:

    from .square import Square

    obj1 = Square()
    obj2 = Square()
    obj3 = obj1.union(obj2)

    print(type(obj3))
    print(obj3.members)

关键点是将 from .union import Union 语句移动到 union() 方法中,直到需要时才会调用它。

这是 Python 循环导入的 good resource

如果您不依赖于模块级导入中的任何内容,您可以将导入放在文件末尾。在 union 的情况下, Primitive 需要在模块范围内定义 class ,因此保持 union.py as-is:

from objects.primitive import Primitive
class Union(Primitive):
    @classmethod
    def union(cls, a, b):
        return Union(a, b)

但是primitive只需要在一个方法中使用Union,而不是在模块范围内创建任何东西,所以你所需要的只是在调用方法时导入的模块已经存在。这意味着您可以这样做:

class Primitive(Base):
    #CODE
    def union(self, obj2):
        return union.Union.union(self, obj2)

from objects import union

之所以需要将导入放在末尾,是为了确保无论先导入哪个模块都能正常工作。如果您导入 objects.union,它将在到达模块主体之前正确导入 objects.primitive。如果您首先导入 objects.primitive,它将尝试导入 objects.union,这需要 Primitive class 已经存在。因此在 class 主体之后导入。

我建议将 union 设为 Union@classmethod,以便您可以将其正确用作替代构造函数。此外,使用 Python 约定,在 CamelCase 中编写 class 名称可以减少命名的混乱。