Defining sub-classes of generic classes
User-defined generic classes and generic classes defined in typing
can be used as base classes for another classes, both generic andnon-generic. For example:
- from typing import Generic, TypeVar, Mapping, Iterator, Dict
- KT = TypeVar('KT')
- VT = TypeVar('VT')
- class MyMap(Mapping[KT, VT]): # This is a generic subclass of Mapping
- def __getitem__(self, k: KT) -> VT:
- ... # Implementations omitted
- def __iter__(self) -> Iterator[KT]:
- ...
- def __len__(self) -> int:
- ...
- items: MyMap[str, int] # Okay
- class StrDict(Dict[str, str]): # This is a non-generic subclass of Dict
- def __str__(self) -> str:
- return 'StrDict({})'.format(super().__str__())
- data: StrDict[int, int] # Error! StrDict is not generic
- data2: StrDict # OK
- class Receiver(Generic[T]):
- def accept(self, value: T) -> None:
- ...
- class AdvancedReceiver(Receiver[T]):
- ...
Note
You have to add an explicit Mapping
base classif you want mypy to consider a user-defined class as a mapping (andSequence
for sequences, etc.). This is because mypy doesn’t usestructural subtyping for these ABCs, unlike simpler protocolslike Iterable
, which use structural subtyping.
Generic
can be omitted from bases if there areother base classes that include type variables, such as Mapping[KT, VT]
in the above example. If you include Generic[…]
in bases, thenit should list all type variables present in other bases (or more,if needed). The order of type variables is defined by the followingrules:
- If
Generic[…]
is present, then the order of variables isalways determined by their order inGeneric[…]
. - If there are no
Generic[…]
in bases, then all type variablesare collected in the lexicographic order (i.e. by first appearance).
For example:
- from typing import Generic, TypeVar, Any
- T = TypeVar('T')
- S = TypeVar('S')
- U = TypeVar('U')
- class One(Generic[T]): ...
- class Another(Generic[T]): ...
- class First(One[T], Another[S]): ...
- class Second(One[T], Another[S], Generic[S, U, T]): ...
- x: First[int, str] # Here T is bound to int, S is bound to str
- y: Second[int, str, Any] # Here T is Any, S is int, and U is str