检查类的子父关系,同时防止循环导入循环依赖关系

问题描述 投票:1回答:2

我有这些模块。

# module 1

from abc import ABC
from module3 import AnotherClass


class Parent(ABC):

    @classmethod
    def func1(cls):

        other_param = "foo"
        AnotherClass.some_func(cls, other_param)
# module 2

from module1 import Parent
from module3 import AnotherClass


class Child1(Parent):

    pass


class Child2(Parent):

    pass
# module 3

from module1 import Parent # only for checking if the object is a subclass of Parent


class AnotherClass(object):

    @classmethod
    def some_func(cls, child_cls, other_param):

        assert issubclass(child_cls, Parent)
        # do other stuff

现在如果我这样做,

c1 = Child1()

c1.func1()

我理所当然地得到了一个ImportError,抱怨是循环导入,如下所示。

ImportError: cannot import name 'Parent' from partially initialized module 'module1' (most likely due to a circular import)

其实 AnotherClass 不取决于 Parent 或任何一个Child类,我导入的是 Parent 只用于检查所传递的类是否为 Parent,在这一行。

assert issubclass(child_cls, Parent)

现在,我可以推迟导入的是 Parent 像这样。

# module 3


class AnotherClass(object):

    @classmethod
    def some_func(cls, child_cls, other_param):

        from module1 import Parent # only for type checking
        assert issubclass(child_cls, Parent)
        # do other stuff

它的工作原理很好 但是由于某些原因(我不知道),我觉得这样做很不舒服。

现在我的问题是,我可以这样推迟进口的时间安然入睡吗,还是以后在路上会以某种方式咬我?

如果可以,你建议我如何做这个父母子女关系检查,在 AnotherClass.some_func()?

P.S.在有人提出来之前,我知道这个循环依赖的话题已经被问过很多很多次,也回答过很多很多次(比如 这个),但我想问的是,这种具体的解决方案是否可行,长期来看是否没有问题。

python python-3.x circular-dependency
2个回答
1
投票

你现在的解决方案没有什么本质上的问题。不过在这种情况下,你也可以这样解决,这样更简洁一些。

import module1


class AnotherClass(object):

    @classmethod
    def some_func(cls, child_cls, other_param):
        assert issubclass(child_cls, module1.Parent)

0
投票

首先,你并没有真正的进行 "类型检查", assert是完全不同的事情,因为它们实际上是在运行时处理的。

我认为你最好使用实际的类型提示,通过使用它们,有一个非常简单和习惯的方法来避免循环导入的问题。

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from module1 import Parent


class AnotherClass:  # No need to inherit from `object` in Python 3.

    @classmethod
    def some_func(cls, child_cls: "Parent", other_param):
        ...
© www.soinside.com 2019 - 2024. All rights reserved.