[Python-checkins] [3.11] Typing docs: improve the guidance on annotating tuples (GH-106021) (#106029)

AlexWaygood webhook-mailer at python.org
Fri Jun 23 10:53:18 EDT 2023


https://github.com/python/cpython/commit/15f4bba7a795de20cc945e8aa61c458a7b30aaa2
commit: 15f4bba7a795de20cc945e8aa61c458a7b30aaa2
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: AlexWaygood <Alex.Waygood at Gmail.com>
date: 2023-06-23T15:53:14+01:00
summary:

[3.11] Typing docs: improve the guidance on annotating tuples (GH-106021) (#106029)

Typing docs: improve the guidance on annotating tuples (GH-106021)
(cherry picked from commit 968435ddb1c1af9333befb26f7970cded8a5c710)

Co-authored-by: Alex Waygood <Alex.Waygood at Gmail.com>

files:
M Doc/library/typing.rst

diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index b9e8534fe956..ddb2f910dcd9 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -324,6 +324,68 @@ called :class:`TypeVar`.
    def first(l: Sequence[T]) -> T:   # Function is generic over the TypeVar "T"
        return l[0]
 
+.. _annotating-tuples:
+
+Annotating tuples
+=================
+
+For most containers in Python, the typing system assumes that all elements in
+the container will be of the same type. For example::
+
+   from collections.abc import Mapping
+
+   # Type checker will infer that all elements in ``x`` are meant to be ints
+   x: list[int] = []
+
+   # Type checker error: ``list`` only accepts a single type argument:
+   y: list[int, str] = [1, 'foo']
+
+   # Type checker will infer that all keys in ``y`` are meant to be strings,
+   # and that all values in ``y`` are meant to be either strings or ints
+   z: Mapping[str, str | int] = {}
+
+:class:`list` only accepts one type argument, so a type checker would emit an
+error on the ``y`` assignment above. Similarly,
+:class:`~collections.abc.Mapping` only accepts two type arguments: the first
+indicates the type of the keys, and the second indicates the type of the
+values.
+
+Unlike most other Python containers, however, it is common in idiomatic Python
+code for tuples to have elements which are not all of the same type. For this
+reason, tuples are special-cased in Python's typing system. :class:`tuple`
+accepts *any number* of type arguments::
+
+   # OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int
+   x: tuple[int] = (5,)
+
+   # OK: ``y`` is assigned to a tuple of length 2;
+   # element 1 is an int, element 2 is a str
+   y: tuple[int, str] = (5, "foo")
+
+   # Error: the type annotation indicates a tuple of length 1,
+   # but ``z`` has been assigned to a tuple of length 3
+   z: tuple[int] = (1, 2, 3)
+
+To denote a tuple which could be of *any* length, and in which all elements are
+of the same type ``T``, use ``tuple[T, ...]``. To denote an empty tuple, use
+``tuple[()]``. Using plain ``tuple`` as an annotation is equivalent to using
+``tuple[Any, ...]``::
+
+   x: tuple[int, ...] = (1, 2)
+   # These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
+   x = (1, 2, 3)
+   x = ()
+   # This reassignment is an error: all elements in ``x`` must be ints
+   x = ("foo", "bar")
+
+   # ``y`` can only ever be assigned to an empty tuple
+   y: tuple[()] = ()
+
+   z: tuple = ("foo", "bar")
+   # These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
+   z = (1, 2, 3)
+   z = ()
+
 .. _user-defined-generics:
 
 User-defined generic types
@@ -819,26 +881,6 @@ Special forms
 These can be used as types in annotations. They all support subscription using
 ``[]``, but each has a unique syntax.
 
-.. data:: Tuple
-
-   Deprecated alias for :class:`tuple`.
-
-   ``Tuple[X, Y]`` is the type of a tuple of two items
-   with the first item of type X and the second of type Y. The type of
-   the empty tuple can be written as ``Tuple[()]``.
-
-   Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding
-   to type variables T1 and T2.  ``Tuple[int, float, str]`` is a tuple
-   of an int, a float and a string.
-
-   To specify a variable-length tuple of homogeneous type,
-   use literal ellipsis, e.g. ``Tuple[int, ...]``. A plain ``Tuple`` annotation
-   is equivalent to ``tuple``, ``Tuple[Any, ...]``, or ``tuple[Any, ...]``.
-
-   .. deprecated:: 3.9
-      :class:`builtins.tuple <tuple>` now supports subscripting (``[]``).
-      See :pep:`585` and :ref:`types-genericalias`.
-
 .. data:: Union
 
    Union type; ``Union[X, Y]`` is equivalent to ``X | Y`` and means either X or Y.
@@ -2785,7 +2827,16 @@ Aliases to built-in types
       now supports subscripting (``[]``).
       See :pep:`585` and :ref:`types-genericalias`.
 
-.. note:: :data:`Tuple` is a special form.
+.. data:: Tuple
+
+   Deprecated alias for :class:`tuple`.
+
+   :class:`tuple` and ``Tuple`` are special-cased in the type system; see
+   :ref:`annotating-tuples` for more details.
+
+   .. deprecated:: 3.9
+      :class:`builtins.tuple <tuple>` now supports subscripting (``[]``).
+      See :pep:`585` and :ref:`types-genericalias`.
 
 .. _corresponding-to-types-in-collections:
 



More information about the Python-checkins mailing list