Skip to content
Merged
Prev Previous commit
Next Next commit
Switch initial example to remove_first_element
  • Loading branch information
mrahtz committed Apr 2, 2022
commit 5362e0377647dd8d2536adb0c78ce96c0a75bb31
42 changes: 23 additions & 19 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1242,33 +1242,37 @@ These are not used in annotations. They are building blocks for creating generic
*arbitrary* number of types by acting like an *arbitrary* number of type
Comment thread
mrahtz marked this conversation as resolved.
variables wrapped in a tuple. For example::

Shape = TypeVarTuple('Shape')
T = TypeVar('T')
Ts = TypeVarTuple('Ts')

def remove_first_element(xs: tuple[T, *Ts]) -> tuple[*Ts]: ...
Comment thread
mrahtz marked this conversation as resolved.
Outdated

remove_first_element(xs=(1,))
# T is bound to int, Ts is bound to ()
# Return type is tuple[()]
Comment thread
mrahtz marked this conversation as resolved.
Outdated

Comment thread
mrahtz marked this conversation as resolved.
class Array(Generic[*Shape]): ...
remove_first_element(xs=(1, '2'))
Comment thread
mrahtz marked this conversation as resolved.
Outdated
# T is bound to int, Ts is bound to (str,)
# Return type is tuple[str]
Comment thread
mrahtz marked this conversation as resolved.
Outdated

array_1d: Array[int] = Array() # 1 type parameter: fine
array_2d: Array[int, int] = Array() # 2 type parameters: also fine
array_0d: Array[()] = Array() # 0 type parameters: also fine
remove_first_element(xs=(1, '2', 3.0))
Comment thread
mrahtz marked this conversation as resolved.
Outdated
# T is bound to int, Ts is bound to (str, float)
# Return type is tuple[str, float]
Comment thread
mrahtz marked this conversation as resolved.
Outdated

Note the use of the unpacking operator ``*`` in ``Generic[*Shape]``.
Conceptually, you can think of ``Shape`` as a tuple of type variables
``(T1, T2, ...)``. ``Generic[*Shape]`` would then become
``Generic[*(T1, T2, ...)]``, which is equivalent to
``Generic[T1, T2, ...]``. (Note that in older versions of Python, you might
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[Shape]``.)
``Unpack[Ts]``.)

Type variable tuples must *always* be unpacked. This helps distinguish type
variable types from normal type variables::

class C(Generic[Shape]): ... # Not valid (should be Generic[*Shape])

In cases where you really do just want a tuple of types, make this explicit
by wrapping the type variable tuple in ``tuple[]``::

shape: Shape # Not valid
shape: tuple[Shape] # Also not valid
shape: tuple[*Shape] # The correct way to do it
x: Ts # Not valid
x: tuple[Ts] # Not valid
x: tuple[*Ts] # The correct way to to do it

Type variable tuples can be used in the same contexts as normal type
variables. For example, in class definitions, arguments, and return types::
Expand Down