When speaking about Generics
, Python gives the following example:
from collections.abc import Sequence
from typing import TypeVar
T = TypeVar('T') # Declare type variable
def first(l: Sequence[T]) -> T: # Generic function
return l[0]
Could someone please explain what TypeVar
does in this case? For example, if it can be anything, why not just give it the value Any
? And if it's constrained, why not give it a Union
value? In other words, what is the usefulness of using TypeVar(...)
?
I suppose in reviewing the above, it's used when an element of some sort of sub-element? For example, it could be:
[{set1}, {set2}, {set3}, ...]
And that type would be Sequence[set] -> set
But something like this:
[1, 2, 3, ...]
Would have type Sequence[int] -> int
. Are there any other usages besides this "item-in-iterable"?
The purpose of the TypeVar
in this context is to say that the function returns a specific type that is related to the argument's type.
For example, if you did:
a = first([1, 2, 3]) + "foo"
you would get an error, because in this expression T
becomes bound to the type int
, and so you'd get an error about adding an int
and a str
.
If you annotated first
with Any
types as you describe, this would not produce a mypy error (and hence you'd get a TypeError
at runtime instead), because the return value of first
would always simply be Any
.
See the mypy documentation on generics for a lot more examples of how to use typevars: https://mypy.readthedocs.io/en/stable/generics.html