Python循环依赖关系,包括成员函数

时间:2019-05-08 01:18:28

标签: python circular-dependency

当我尝试将现有函数作为成员函数合并到类中时,就会出现此问题。我有类似的设置:

课程:

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

我有一个名为union的函数,用户可以调用该函数返回一个union基本对象。

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

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

obj3 = obj1.union(obj2)

这就是问题所在。 primitive类需要导入union函数,后者又导入union类,后者又导入primitive类,并且遇到循环依赖项错误。是否有一种聪明的方法来重构代码或更改导入语句以使其工作?

编辑:

为清楚起见,这是代码的结构方式:

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 (该类)

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的类,该类包含有关联合输入对象的信息。用户不会与此交互。然后是用户可以调用的union函数,该函数返回一个union对象。我希望primitive类包含一个名为union的成员函数,该成员函数使用我已经编写的union函数。问题是union函数返回一个union类的primitive对象。这会导致循环依赖性问题。我可以删除union成员函数,但用户不能这样做

obj3 = obj1.union(obj2)

2 个答案:

答案 0 :(得分:1)

听起来好像您通过在单独的模块/文件中定义primitivesquare给自己造成了很多麻烦。如果您在同一模块中定义它们,我怀疑您会遇到麻烦。例如,以下可以正常工作:

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

答案 1 :(得分:1)

如果您在模块级别不依赖任何导入,则可以将导入放置在文件的末尾。对于union,需要Primitive在模块范围内定义一个类,因此请按原样保留union.py

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类已经存在。因此,导入到类主体之后。

我建议将union中的@classmethod设为Union的{​​{1}},以便您可以正确地将其用作备用构造函数。另外,使用CamelCase中编写类名的Python约定可以使命名更容易混淆。