在防止循环导入/循环依赖的同时进行类型检查

我有以下模块:

# 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 type checking


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:无法从部分初始化的名称中导入名称“父母”   模块“ module1”(很可能是由于循环导入)

Actually AnotherClass does not depend on Parent or any of the Child classes, I'm importing the Parent only for type checking in assertion at this row:

assert issubclass(child_cls, Parent)

Now, I can defer importing of the Parent like this:

# 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

它就像一种魅力。但是由于某种原因(我不知道),我以这种方式感到不舒服。

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

If yes, how would you suggest I do the type checking at AnotherClass.some_func()?

P.S. Before anyone brings it up, I know this topic of circular dependencies has been asked and answered many many times (such as this one), but I'm asking if this specific solution is feasible and problem-free in the long run.

评论
hiure
hiure

First of all, you are not really doing "type checking" there, asserts are a completely different thing, since they are actually processed at run time.

我认为最好使用实际的类型提示,并且通过使用它们,有一种非常简单且惯用的方式来避免循环导入问题:

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):
        ...
点赞
评论