I'm not able to understand the use of Generic and TypeVar, and how they are related.
https://docs.python.org/3/library/typing.html#building-generic-types
The docs have this example:
class Mapping(Generic[KT, VT]):
def __getitem__(self, key: KT) -> VT:
...
# Etc.
X = TypeVar('X')
Y = TypeVar('Y')
def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
try:
return mapping[key]
except KeyError:
return default
Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions.
What can't I simply use Mapping with some existing type, like int, instead of creating X and Y?
The whole purporse of using X and Y is when one wants the parameters to be as generic as possible. int can be used, instead. The difference is: the static analyzer will interpret the parameter as always being an int. Using X and Y means the function accepts any type of parameter. The static analyzer, as in an IDE - for instance, will determine the type of X and Y, and thus the return type, as arguments of type X and Y are provided on function call.
mapping: Mapping[str, int] = {"2": 2, "3": 3}
name = lookup_name(mapping, "1", 1)
In the above example type checkers will know name will always be an int relying on the type annotations. In IDEs, code completion for int methods will be shown.
Using specific types is the ideal if that is your goal. The function accepting only a map with int keys or values, and/or returning int.
You can change X and Y to any type want, basically. That is a broad example.
Below example is possible:
def lookup_name(mapping: Mapping[str, int], key: str, default: int) -> int:
try:
return mapping[key]
except KeyError:
return default
The types are not Generic in the above example. The key will always be str; the value, the default and the return type will always be an int. It's the programmer's choice. This is not enforced by Python, though. A static type checker like mypy is needed for that.
As explained by @mistermiyagi, X and Y are basically variables which represent types in Python.
The Generic type could even be constrained if wanted:
import typing
X = typing.TypeVar("X", int, str)
Y = typing.TypeVar("Y", int)