Question: I am facing a circular import error when I define type aliases for the subclasses of an abstract class. This is an example of what I'm trying to achieve: #abstract_file_builder.py from abc import ABC, abstractmethod from typing import Generic, MutableSequence, TypeVar from mymodule.type_a_file_builder import TypeARow from mymodule.type_b_file_builder import TypeBRow GenericRow = TypeVar("GenericRow", TypeARow, TypeBRow) class AbstractFileBuilder(ABC, Generic[GenericRow]): ... @abstractmethod def generate_rows( self, ) -> MutableSequence[GenericRow]: pass  #type_a_file_builder.py from typing import Any, MutableSequence from mymodule.abstract_file_builder import AbstractFileBuilder TypeARow = MutableSequence[Any] class TypeAFileBuilder(AbstractFileBuilder[TypeARow]): ... def generate_rows( self, ) -> MutableSequence[TypeARow]: ... # Code logic for TypeA return rows  #type_b_file_builder.py from typing import MutableSequence, Union from mymodule.abstract_file_builder import AbstractFileBuilder TypeBRow = MutableSequence[Union[int, float]] class TypeBFileBuilder(AbstractFileBuilder[TypeBRow]): ... def generate_rows( self, ) -> MutableSequence[TypeBRow]: ... # Code logic for TypeB return rows  What is the most pythonic way to solve this? I know I can use the TYPE_CHECKING variable to avoid runtime imports, but that feels like a patch instead of a good solution. Another thing that can solve the problem is to define the type aliases in the abstract class, but that would ruin the whole purpose of having an abstract class and not having to know what's implemented below. I'm not sure however if I can do some form of an "abstract" type alias inside the abstract_file_builder.py file, and then declare the TypeARow and TypeBRow types as children of that abstract type. I must note that the solution must work with, at least, Python 3.9. If it supports versions back to 3.7 it'll be better, but not super necessary.

Answer: By placing the following line in your abstract class you kind of add information of your concrete subclasses to your abstract class: GenericRow = TypeVar("GenericRow", TypeARow, TypeBRow)  That doesn't look right to me. I think you should rather remove this dependency, because in consequence it would mean, that you potentially would have to change the definiton of the return type of your abstract method again in case you add another subclass later. I would only consider this in case you think your subclasses are pretty fixed and neither the return type changes nor new subclasses are added. In that case, you could just put the three classes in one file and put the definitions of the return types before the definition of your abstract class. But because we usually do not know if we add other subclasses later (why would we care about creating abstract superclasses otherwise), I think the superclass should not have knowledge about the subclasses. In that case I would rather type the abstract method with the broader type, e.g. like this: #abstract_file_builder.py from abc import ABC, abstractmethod from typing import Generic, MutableSequence, TypeVar class AbstractFileBuilder(ABC): ... @abstractmethod def generate_rows( self, ) -> MutableSequence[Any]: pass