Note that ``None`` as a type hint is a special case and is replaced by
``type(None)``.
+Type aliases may be marked with :data:`TypeAlias` to make it explicit that
+the statement is a type alias declaration, not a normal variable assignment::
+
+ from typing import TypeAlias
+
+ Vector: TypeAlias = list[float]
+
.. _distinct:
NewType
class LinkedList(Sized, Generic[T]):
...
-When inheriting from generic classes, some type variables could be fixed::
+When inheriting from generic classes, some type parameters could be fixed::
- from collections.abc import Mapping
- from typing import TypeVar
+ from collections.abc import Mapping
+ from typing import TypeVar
- T = TypeVar('T')
+ T = TypeVar('T')
- class MyDict(Mapping[str, T]):
- ...
+ class MyDict(Mapping[str, T]):
+ ...
In this case ``MyDict`` has a single parameter, ``T``.
class MyIterable(Iterable): # Same as Iterable[Any]
-User defined generic type aliases are also supported. Examples::
+User-defined generic type aliases are also supported. Examples::
from collections.abc import Iterable
from typing import TypeVar
>>> Z[int, [dict, float]]
__main__.Z[int, (<class 'dict'>, <class 'float'>)]
-
Furthermore, a generic with only one parameter specification variable will accept
parameter lists in the forms ``X[[Type1, Type2, ...]]`` and also
``X[Type1, Type2, ...]`` for aesthetic reasons. Internally, the latter is converted
This can be used to define a function that should never be
called, or a function that never returns::
- from typing import Never
+ from typing import Never
- def never_call_me(arg: Never) -> None:
- pass
+ def never_call_me(arg: Never) -> None:
+ pass
- def int_or_str(arg: int | str) -> None:
- never_call_me(arg) # type checker error
- match arg:
- case int():
- print("It's an int")
- case str():
- print("It's a str")
- case _:
- never_call_me(arg) # ok, arg is of type Never
+ def int_or_str(arg: int | str) -> None:
+ never_call_me(arg) # type checker error
+ match arg:
+ case int():
+ print("It's an int")
+ case str():
+ print("It's a str")
+ case _:
+ never_call_me(arg) # ok, arg is of type Never
.. versionadded:: 3.11
from typing import Self
class Foo:
- def return_self(self) -> Self:
- ...
- return self
+ def return_self(self) -> Self:
+ ...
+ return self
This annotation is semantically equivalent to the following,
Self = TypeVar("Self", bound="Foo")
class Foo:
- def return_self(self: Self) -> Self:
- ...
- return self
+ def return_self(self: Self) -> Self:
+ ...
+ return self
In general if something currently follows the pattern of::
class Foo:
- def return_self(self) -> "Foo":
- ...
- return self
+ def return_self(self) -> "Foo":
+ ...
+ return self
You should use :data:`Self` as calls to ``SubclassOfFoo.return_self`` would have
``Foo`` as the return type and not ``SubclassOfFoo``.
Building generic types
""""""""""""""""""""""
-These are not used in annotations. They are building blocks for creating generic types.
+The following objects are not used directly in annotations. Instead, they are building blocks
+for creating generic types.
.. class:: Generic
except KeyError:
return default
-.. class:: TypeVar
+.. class:: TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False)
- Type variable.
+ Type variable.
- Usage::
+ Usage::
T = TypeVar('T') # Can be anything
S = TypeVar('S', bound=str) # Can be any subtype of str
A = TypeVar('A', str, bytes) # Must be exactly str or bytes
- 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. See :class:`Generic` for more
- information on generic types. Generic functions work as follows::
+ 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 and type alias definitions.
+ See :class:`Generic` for more
+ information on generic types. Generic functions work as follows::
+
+ def repeat(x: T, n: int) -> Sequence[T]:
+ """Return a list containing n references to x."""
+ return [x]*n
+
+
+ def print_capitalized(x: S) -> S:
+ """Print x capitalized, and return x."""
+ print(x.capitalize())
+ return x
+
+
+ def concatenate(x: A, y: A) -> A:
+ """Add two strings or bytes objects together."""
+ return x + y
+
+ Note that type variables can be *bound*, *constrained*, or neither, but
+ cannot be both bound *and* constrained.
- def repeat(x: T, n: int) -> Sequence[T]:
- """Return a list containing n references to x."""
- return [x]*n
+ Created type variables may be explicitly marked covariant or contravariant by passing
+ ``covariant=True`` or ``contravariant=True``.
+ By default, type variables are invariant.
+ See :pep:`484` and :pep:`695` for more details.
+ Bound type variables and constrained type variables have different
+ semantics in several important ways. Using a *bound* type variable means
+ that the ``TypeVar`` will be solved using the most specific type possible::
- def print_capitalized(x: S) -> S:
- """Print x capitalized, and return x."""
- print(x.capitalize())
- return x
+ x = print_capitalized('a string')
+ reveal_type(x) # revealed type is str
+ class StringSubclass(str):
+ pass
- def concatenate(x: A, y: A) -> A:
- """Add two strings or bytes objects together."""
- return x + y
+ y = print_capitalized(StringSubclass('another string'))
+ reveal_type(y) # revealed type is StringSubclass
- Note that type variables can be *bound*, *constrained*, or neither, but
- cannot be both bound *and* constrained.
+ z = print_capitalized(45) # error: int is not a subtype of str
- Bound type variables and constrained type variables have different
- semantics in several important ways. Using a *bound* type variable means
- that the ``TypeVar`` will be solved using the most specific type possible::
+ Type variables can be bound to concrete types, abstract types (ABCs or
+ protocols), and even unions of types::
- x = print_capitalized('a string')
- reveal_type(x) # revealed type is str
+ U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes
+ V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
- class StringSubclass(str):
- pass
+ .. _typing-constrained-typevar:
- y = print_capitalized(StringSubclass('another string'))
- reveal_type(y) # revealed type is StringSubclass
+ Using a *constrained* type variable, however, means that the ``TypeVar``
+ can only ever be solved as being exactly one of the constraints given::
- z = print_capitalized(45) # error: int is not a subtype of str
+ a = concatenate('one', 'two')
+ reveal_type(a) # revealed type is str
- Type variables can be bound to concrete types, abstract types (ABCs or
- protocols), and even unions of types::
+ b = concatenate(StringSubclass('one'), StringSubclass('two'))
+ reveal_type(b) # revealed type is str, despite StringSubclass being passed in
- U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes
- V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
+ c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not both
-.. _typing-constrained-typevar:
+ At runtime, ``isinstance(x, T)`` will raise :exc:`TypeError`.
- Using a *constrained* type variable, however, means that the ``TypeVar``
- can only ever be solved as being exactly one of the constraints given::
+ .. attribute:: __name__
+
+ The name of the type variable.
+
+ .. attribute:: __covariant__
+
+ Whether the type var has been marked as covariant.
+
+ .. attribute:: __contravariant__
- a = concatenate('one', 'two')
- reveal_type(a) # revealed type is str
+ Whether the type var has been marked as contravariant.
- b = concatenate(StringSubclass('one'), StringSubclass('two'))
- reveal_type(b) # revealed type is str, despite StringSubclass being passed in
+ .. attribute:: __bound__
- c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not both
+ The bound of the type variable, if any.
- At runtime, ``isinstance(x, T)`` will raise :exc:`TypeError`. In general,
- :func:`isinstance` and :func:`issubclass` should not be used with types.
+ .. attribute:: __constraints__
- Type variables may be marked covariant or contravariant by passing
- ``covariant=True`` or ``contravariant=True``. See :pep:`484` for more
- details. By default, type variables are invariant.
+ A tuple containing the constraints of the type variable, if any.
+
+.. class:: TypeVarTuple(name)
+
+ Type variable tuple. A specialized form of :class:`type variable <TypeVar>`
+ that enables *variadic* generics.
+
+ Usage::
-.. class:: TypeVarTuple
+ T = TypeVar("T")
+ Ts = TypeVarTuple("Ts")
- Type variable tuple. A specialized form of :class:`type variable <TypeVar>`
- that enables *variadic* generics.
+ def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
+ return (*tup[1:], tup[0])
- A normal type variable enables parameterization with a single type. A type
- variable tuple, in contrast, allows parameterization with an
- *arbitrary* number of types by acting like an *arbitrary* number of type
- variables wrapped in a tuple. For example::
+ A normal type variable enables parameterization with a single type. A type
+ variable tuple, in contrast, allows parameterization with an
+ *arbitrary* number of types by acting like an *arbitrary* number of type
+ variables wrapped in a tuple. For example::
- T = TypeVar('T')
- Ts = TypeVarTuple('Ts')
+ # T is bound to int, Ts is bound to ()
+ # Return value is (1,), which has type tuple[int]
+ move_first_element_to_last(tup=(1,))
- def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
- return (*tup[1:], tup[0])
+ # T is bound to int, Ts is bound to (str,)
+ # Return value is ('spam', 1), which has type tuple[str, int]
+ move_first_element_to_last(tup=(1, 'spam'))
- # T is bound to int, Ts is bound to ()
- # Return value is (1,), which has type tuple[int]
- move_first_element_to_last(tup=(1,))
+ # T is bound to int, Ts is bound to (str, float)
+ # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int]
+ move_first_element_to_last(tup=(1, 'spam', 3.0))
- # T is bound to int, Ts is bound to (str,)
- # Return value is ('spam', 1), which has type tuple[str, int]
- move_first_element_to_last(tup=(1, 'spam'))
+ # This fails to type check (and fails at runtime)
+ # because tuple[()] is not compatible with tuple[T, *Ts]
+ # (at least one element is required)
+ move_first_element_to_last(tup=())
- # T is bound to int, Ts is bound to (str, float)
- # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int]
- move_first_element_to_last(tup=(1, 'spam', 3.0))
+ Note the use of the unpacking operator ``*`` in ``tuple[T, *Ts]``.
+ Conceptually, you can think of ``Ts`` as a tuple of type variables
+ ``(T1, T2, ...)``. ``tuple[T, *Ts]`` would then become
+ ``tuple[T, *(T1, T2, ...)]``, which is equivalent to
+ ``tuple[T, T1, T2, ...]``. (Note that in older versions of Python, you might
+ see this written using :data:`Unpack <Unpack>` instead, as
+ ``Unpack[Ts]``.)
- # This fails to type check (and fails at runtime)
- # because tuple[()] is not compatible with tuple[T, *Ts]
- # (at least one element is required)
- move_first_element_to_last(tup=())
+ Type variable tuples must *always* be unpacked. This helps distinguish type
+ variable tuples from normal type variables::
- Note the use of the unpacking operator ``*`` in ``tuple[T, *Ts]``.
- Conceptually, you can think of ``Ts`` as a tuple of type variables
- ``(T1, T2, ...)``. ``tuple[T, *Ts]`` would then become
- ``tuple[T, *(T1, T2, ...)]``, which is equivalent to
- ``tuple[T, T1, T2, ...]``. (Note that in older versions of Python, you might
- see this written using :data:`Unpack <Unpack>` instead, as
- ``Unpack[Ts]``.)
+ x: Ts # Not valid
+ x: tuple[Ts] # Not valid
+ x: tuple[*Ts] # The correct way to do it
- Type variable tuples must *always* be unpacked. This helps distinguish type
- variable tuples from normal type variables::
+ Type variable tuples can be used in the same contexts as normal type
+ variables. For example, in class definitions, arguments, and return types::
- x: Ts # Not valid
- x: tuple[Ts] # Not valid
- x: tuple[*Ts] # The correct way to do it
+ Shape = TypeVarTuple("Shape")
+ class Array(Generic[*Shape]):
+ def __getitem__(self, key: tuple[*Shape]) -> float: ...
+ def __abs__(self) -> "Array[*Shape]": ...
+ def get_shape(self) -> tuple[*Shape]: ...
- Type variable tuples can be used in the same contexts as normal type
- variables. For example, in class definitions, arguments, and return types::
+ Type variable tuples can be happily combined with normal type variables::
- Shape = TypeVarTuple('Shape')
- class Array(Generic[*Shape]):
- def __getitem__(self, key: tuple[*Shape]) -> float: ...
- def __abs__(self) -> "Array[*Shape]": ...
- def get_shape(self) -> tuple[*Shape]: ...
+ DType = TypeVar('DType')
- Type variable tuples can be happily combined with normal type variables::
+ class Array(Generic[DType, *Shape]): # This is fine
+ pass
- DType = TypeVar('DType')
+ class Array2(Generic[*Shape, DType]): # This would also be fine
+ pass
- class Array(Generic[DType, *Shape]): # This is fine
- pass
+ float_array_1d: Array[float, Height] = Array() # Totally fine
+ int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
- class Array2(Generic[*Shape, DType]): # This would also be fine
- pass
+ However, note that at most one type variable tuple may appear in a single
+ list of type arguments or type parameters::
- float_array_1d: Array[float, Height] = Array() # Totally fine
- int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
+ x: tuple[*Ts, *Ts] # Not valid
+ class Array(Generic[*Shape, *Shape]): # Not valid
+ pass
- However, note that at most one type variable tuple may appear in a single
- list of type arguments or type parameters::
+ Finally, an unpacked type variable tuple can be used as the type annotation
+ of ``*args``::
- x: tuple[*Ts, *Ts] # Not valid
- class Array(Generic[*Shape, *Shape]): # Not valid
- pass
+ def call_soon(
+ callback: Callable[[*Ts], None],
+ *args: *Ts
+ ) -> None:
+ ...
+ callback(*args)
- Finally, an unpacked type variable tuple can be used as the type annotation
- of ``*args``::
+ In contrast to non-unpacked annotations of ``*args`` - e.g. ``*args: int``,
+ which would specify that *all* arguments are ``int`` - ``*args: *Ts``
+ enables reference to the types of the *individual* arguments in ``*args``.
+ Here, this allows us to ensure the types of the ``*args`` passed
+ to ``call_soon`` match the types of the (positional) arguments of
+ ``callback``.
- def call_soon(
- callback: Callable[[*Ts], None],
- *args: *Ts
- ) -> None:
- ...
- callback(*args)
+ See :pep:`646` for more details on type variable tuples.
- In contrast to non-unpacked annotations of ``*args`` - e.g. ``*args: int``,
- which would specify that *all* arguments are ``int`` - ``*args: *Ts``
- enables reference to the types of the *individual* arguments in ``*args``.
- Here, this allows us to ensure the types of the ``*args`` passed
- to ``call_soon`` match the types of the (positional) arguments of
- ``callback``.
+ .. attribute:: __name__
- See :pep:`646` for more details on type variable tuples.
+ The name of the type variable tuple.
- .. versionadded:: 3.11
+ .. versionadded:: 3.11
.. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False)
``P.args`` and ``P.kwargs`` are instances respectively of
:class:`ParamSpecArgs` and :class:`ParamSpecKwargs`.
+ .. attribute:: __name__
+
+ The name of the parameter specification.
+
Parameter specification variables created with ``covariant=True`` or
``contravariant=True`` can be used to declare covariant or contravariant
generic types. The ``bound`` argument is also accepted, similar to
Protocol classes can be generic, for example::
+ T = TypeVar("T")
+
class GenProto(Protocol[T]):
def meth(self) -> T:
...
A generic version of :class:`collections.abc.Mapping`.
This type can be used as follows::
- def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
- return word_list[word]
+ def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
+ return word_list[word]
.. deprecated:: 3.9
:class:`collections.abc.Mapping` now supports subscripting (``[]``).