I am trying to understand the type hint Getter[T]
in the following piece of code:
Simplified example
T = TypeVar('T')
Getter = Callable[[T, str], str]
class AbstractClass(abc.ABC):
@abc.abstractmethod
def extract(
self,
get_from_carrier: Getter[T], # <---- See here
...
) -> Context:
Help much appreciated since I have been breaking my head over this.
Original source code
The original source code is from the OpenTelemetry project file "textmap.py":
import abc
import typing
from opentelemetry.context.context import Context
TextMapPropagatorT = typing.TypeVar("TextMapPropagatorT")
Setter = typing.Callable[[TextMapPropagatorT, str, str], None]
Getter = typing.Callable[[TextMapPropagatorT, str], typing.List[str]]
class TextMapPropagator(abc.ABC):
"""This class provides an interface that enables extracting and injecting
context into headers of HTTP requests.
...
"""
@abc.abstractmethod
def extract(
self,
get_from_carrier: Getter[TextMapPropagatorT],
carrier: TextMapPropagatorT,
context: typing.Optional[Context] = None,
) -> Context:
tl;dr:
_C[_T]
is a generic type alias that's equivalent toCallable[[_T, int], int]
.Here you're defining
_C
to be the type alias ofCallable[[_T, int], int]
. When an type alias contains aTypeVar
(in this case,_T
), it becomes a generic type alias. You can use it the same way as you'd use built-in generic types likeList[T]
orDict[K, V]
, for example,_C[str]
would be equivalent toCallable[[str, int], int]
.Then, type annotations of
get_from_elem
define it as a generic function. What this means is the the same type variable used within the entire function should be bound to the same class. To explain what this means, take a look at these function calls:In the last two cases, the first argument is a generic function, which does not bind the type variable, so the type variable is only bound by the second argument. However, in the last case,
foo_str_like
has an additional constraint on its first argument type, and the bound typefloat
does not satisfy that constraint, so it fails type checking.