Until Python 3.9 added support for type hinting using standard collections, you had to use typing.Tuple
and typing.List
if you wanted to document what type the contents of the containers needed to be:
def f(points: Tuple[float, float]):
return map(do_stuff, points)
Up until Python 3.8, tuple
and list
did not support being used as generic types. The above example documents that the function f
requires the points
argument to be a tuple with two float
values.
typing.Tuple
is special here in that it lets you specify a specific number of elements expected and the type of each position. Use ellipsis if the length is not set and the type should be repeated: Tuple[float, ...]
describes a variable-length tuple
with float
s.
For typing.List
and other sequence types you generally only specify the type for all elements; List[str]
is a list of strings, of any size. Note that functions should preferentially take typing.Sequence
as arguments and typing.List
is typically only used for return types; generally speaking most functions would take any sequence and only iterate, but when you return a list
, you really are returning a specific, mutable sequence type.
If you still need to support Python 3.8 or older code, you should always pick the typing
generics even when you are not currently restricting the contents. It is easier to add that constraint later with a generic type as the resulting change will be smaller.
If you are implementing a custom container type and want that type to support generics, you can implement a __class_getitem__
hook or inherit from typing.Generic
(which in turn implements __class_getitem__
).