我有这些模块。
# 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.在有人提出来之前,我知道这个循环依赖的话题已经被问过很多很多次,也回答过很多很多次(比如 这个),但我想问的是,这种具体的解决方案是否可行,长期来看是否没有问题。
你现在的解决方案没有什么本质上的问题。不过在这种情况下,你也可以这样解决,这样更简洁一些。
import module1
class AnotherClass(object):
@classmethod
def some_func(cls, child_cls, other_param):
assert issubclass(child_cls, module1.Parent)
首先,你并没有真正的进行 "类型检查", 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):
...