I have these modules:
# 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
now if I do this:
c1 = Child1()
c1.func1()
I rightfully get an ImportError complaining from a circular import as follows:
ImportError: cannot import name 'Parent' from partially initialized module 'module1' (most likely due to a circular import)
Actually AnotherClass
does not depend on Parent
or any of the Child classes, I'm importing the Parent
only for checking if the passed class is a subclass of Parent
, in 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
And it works like a charm. But for some reason (unknown to me) I feel uncomfortable doing it this way.
Now my question is, can I sleep with peace deferring the import like that, or would it bite me in some way later on down the road?
If yes, how would you suggest I do the this parent / child relationship check 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.
There's nothing inherently wrong with your current solution. In this case you could also solve it like this though, which is imo a bit cleaner:
import module1
class AnotherClass(object):
@classmethod
def some_func(cls, child_cls, other_param):
assert issubclass(child_cls, module1.Parent)