首页 > 解决方案 > 如何避免循环依赖?

问题描述

我有两个文件,它们都定义了一个类。

project/
    __init__.py
    thing.py
    thinglist.py

thing.py定义了一个类Thing,可以输出其他Things的列表:

# thing.py
from project.thinglist import ThingList
class Thing:
    def make_more_things(self):
        return ThingList(Thing(), Thing())

AThingList是一个Thing对象列表,它扩展了列表并添加了一些其他函数:

# thinglist.py
from project.thing import Thing
class ThingList(list):
    def __init__(self, *args):
        list.__init__(self, *args)
        assert all([isinstance(t, Thing) for t in self])
    def some_other_method: pass

我们立即遇到了一个问题:循环依赖。Thing需要ThingList才能构建ThingListsThingList需要Thing以验证它是由且仅由Things 制成的。但是 Python 不会让我Thing导入thinglist.py.

为了解决这个问题,我可以将两个类放到同一个文件中。但是它们都很长,为了我自己的理智,我真的不想这样做。我也可以省略isinstance检查,但是我可能会遇到现在可以轻松解决的错误。

如何在不合并两个文件的情况下避免这种循环依赖?

标签: pythonpython-3.xcircular-dependency

解决方案


如果指定容器数据类型的唯一目的是执行测试,您可以编写一个具有所有逻辑(追加、类型检查)的类模板类 Container,并且Thing稍后仅将其子类化为容器类型thing.py

例如,在thinglist.py你会有

class Container:

    def __init__(self):
        if not hasattr(self, 'type_ref'):
            raise NotImplementedError("Type should be set in subclass")
        self._data = []

    def append(self, elt):
        if not isinstance(elt, self.type_ref):
            raise TypeError(f'Element should be of type {self.type_ref}')
        self._data.append(elt)

    ... # rest of the logic

并且在thing.py

from thinglist import Container

class ThingList(Container):
    type_ref = Thing

推荐阅读