From e22fb2853a0f6e06febc0a4274da1657246b7cb8 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 10 Oct 2020 01:43:22 +0800 Subject: [PATCH 1/9] Documentation for GenericAlias --- Doc/glossary.rst | 7 ++ Doc/library/stdtypes.rst | 106 ++++++++++++++++++ Doc/library/types.rst | 5 + .../2020-10-10-01-36-37.bpo-41805.l-CGv5.rst | 3 + 4 files changed, 121 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2020-10-10-01-36-37.bpo-41805.l-CGv5.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 9fdbdb1a83f280..bfa304ad10d88a 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -476,6 +476,13 @@ Glossary See also the :term:`single dispatch` glossary entry, the :func:`functools.singledispatch` decorator, and :pep:`443`. + generic type + A :term:`type` that can be parameterized; typically a container like + :class:`list`. Used for :term:`type hints ` and + :term:`annotations `. + + See :pep:`483` for more details, and :mod:`typing` or + :ref:`generic alias type ` for its uses. GIL See :term:`global interpreter lock`. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 5c6acc66bb4cc3..0ac4fc94b84172 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4749,6 +4749,112 @@ define these methods must provide them as a normal Python accessible method. Compared to the overhead of setting up the runtime context, the overhead of a single class dictionary lookup is negligible. + +.. _types-genericalias: + +Generic Alias Type +================== + +.. index:: + object: GenericAlias + pair: Generic; Alias + +The ``GenericAlias`` object acts as a proxy for :term:`generic types +`, implementing *parameterized generics* - a specific instance +of a generic with the types for container elements provided. It is intended +primarily for type :term:`annotations `. ``GenericAlias`` objects +are returned by expressions like ``list[int]``. + +.. describe:: generic[X, Y, ...] + + Defines a generic containing elements of types *X*, *Y*, and more depending + on the *generic* used. For example, for a function expecting a :class:`list` + containing :class:`float` elements:: + + def average(values: list[float]) -> float: + return sum(values) / len(values) + + Another example for :term:`mapping` objects, using a :class:`dict`. In this + case, the expected ``dict`` has keys of type :class:`str` and their + corresponding values are lists which hold :class:`int` elements:: + + def send_request(message_body: dict[str, list[int]]) -> None: + ... + +The builtin functions :func:`isinstance` and :func:`issubclass` do not accept +parameterized generic types for their second argument:: + + >>> isinstance([1, 2], list[str]) + Traceback (most recent call last): + File "", line 1, in + TypeError: isinstance() argument 2 cannot be a parameterized generic + >>> issubclass(list, list[str]) + Traceback (most recent call last): + File "", line 1, in + TypeError: issubclass() argument 2 cannot be a parameterized generic + +Generic types erase type parameters during object creation:: + + list[int]() == [] + +Furthermore, type parameters are not checked by the Python interpreter during +object creation when using a generic type:: + + list[str]([1, 2, 3]) == list[int]([1, 2, 3]) + +The following collections are generics. Most of their type parameters +can be found in the :mod:`typing` module: + +* :class:`tuple` +* :class:`list` +* :class:`dict` +* :class:`set` +* :class:`frozenset` +* :class:`type` +* :class:`collections.deque` +* :class:`collections.defaultdict` +* :class:`collections.OrderedDict` +* :class:`collections.Counter` +* :class:`collections.ChainMap` +* :class:`collections.abc.Awaitable` +* :class:`collections.abc.Coroutine` +* :class:`collections.abc.AsyncIterable` +* :class:`collections.abc.AsyncIterator` +* :class:`collections.abc.AsyncGenerator` +* :class:`collections.abc.Iterable` +* :class:`collections.abc.Iterator` +* :class:`collections.abc.Generator` +* :class:`collections.abc.Reversible` +* :class:`collections.abc.Container` +* :class:`collections.abc.Collection` +* :class:`collections.abc.Callable` +* :class:`collections.abc.Set` +* :class:`collections.abc.MutableSet` +* :class:`collections.abc.Mapping` +* :class:`collections.abc.MutableMapping` +* :class:`collections.abc.Sequence` +* :class:`collections.abc.MutableSequence` +* :class:`collections.abc.ByteString` +* :class:`collections.abc.MappingView` +* :class:`collections.abc.KeysView` +* :class:`collections.abc.ItemsView` +* :class:`collections.abc.ValuesView` +* :class:`contextlib.AbstractContextManager` +* :class:`contextlib.AbstractAsyncContextManager` +* :ref:`re.Pattern ` +* :ref:`re.Match ` + +The type for the ``GenericAlias`` object is :data:`types.GenericAlias`. + +.. seealso:: + + * :pep:`585` -- "Type Hinting Generics In Standard Collections" + * :meth:`__class_getitem__` -- Method used to parameterize contained types. + in generics + +.. versionadded:: 3.9 + + .. _types-union: Union Type diff --git a/Doc/library/types.rst b/Doc/library/types.rst index e4a8dec5cb95a1..3fcd6eb6bcc31f 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -256,6 +256,11 @@ Standard names are defined for the following types: .. versionadded:: 3.10 +.. data:: GenericAlias + + The type of :ref:`parameterized generics ` such as + ``list[int]``. + .. data:: Union The type of :ref:`union type expressions`. diff --git a/Misc/NEWS.d/next/Documentation/2020-10-10-01-36-37.bpo-41805.l-CGv5.rst b/Misc/NEWS.d/next/Documentation/2020-10-10-01-36-37.bpo-41805.l-CGv5.rst new file mode 100644 index 00000000000000..9c9134350a3176 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-10-10-01-36-37.bpo-41805.l-CGv5.rst @@ -0,0 +1,3 @@ +Documented :ref:`generic alias type ` and +:data:`types.GenericAlias`. Also added an entry in glossary for +:term:`generic types `. From 072dd2424081785147439f42e8b101046ae43a19 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 10 Oct 2020 01:57:59 +0800 Subject: [PATCH 2/9] add versionadded for types --- Doc/library/types.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 3fcd6eb6bcc31f..843876b3d6849b 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -261,6 +261,8 @@ Standard names are defined for the following types: The type of :ref:`parameterized generics ` such as ``list[int]``. + .. versionadded:: 3.9 + .. data:: Union The type of :ref:`union type expressions`. From 96a42f57e0f5c761859bc09d7daa1519c0253eb6 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 11 Oct 2020 00:22:35 +0800 Subject: [PATCH 3/9] docs for special attributes and more explanations --- Doc/library/stdtypes.rst | 96 +++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 11 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 0ac4fc94b84172..b46f4fa849e20f 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4765,6 +4765,8 @@ of a generic with the types for container elements provided. It is intended primarily for type :term:`annotations `. ``GenericAlias`` objects are returned by expressions like ``list[int]``. +The type for the ``GenericAlias`` object is :data:`types.GenericAlias`. + .. describe:: generic[X, Y, ...] Defines a generic containing elements of types *X*, *Y*, and more depending @@ -4775,10 +4777,11 @@ are returned by expressions like ``list[int]``. return sum(values) / len(values) Another example for :term:`mapping` objects, using a :class:`dict`. In this - case, the expected ``dict`` has keys of type :class:`str` and their - corresponding values are lists which hold :class:`int` elements:: + case, the function expects a ``dict`` for its ``body`` argument. The ``body`` + has keys of type :class:`str` and their corresponding values are lists which + hold :class:`int` elements:: - def send_request(message_body: dict[str, list[int]]) -> None: + def send_post_request(url: str, body: dict[str, list[int]]) -> None: ... The builtin functions :func:`isinstance` and :func:`issubclass` do not accept @@ -4788,22 +4791,59 @@ parameterized generic types for their second argument:: Traceback (most recent call last): File "", line 1, in TypeError: isinstance() argument 2 cannot be a parameterized generic + >>> >>> issubclass(list, list[str]) Traceback (most recent call last): File "", line 1, in TypeError: issubclass() argument 2 cannot be a parameterized generic -Generic types erase type parameters during object creation:: +The Python runtime does not enforce type :term:`annotations `. +This extends to generic types and their type parameters. When creating +an object from a parameterized generic, container elements are not checked +against their type. For example, the following code is discouraged, but will +run without errors:: + + >>> t = list[str] + >>> t([1, 2, 3]) + [1, 2, 3] + +Furthermore, parameterized generics erase type parameters during object +creation:: + + >>> t = list[str] + >>> type(t) + + >>> + >>> l = t() + >>> type(l) + + +Calling :func:`repr` on a generic shows the parameterized type:: + + >>> repr(list[int]) + 'list[int]' - list[int]() == [] +The :meth:`__getitem__` method of generics will raise an exception to disallow +mistakes like ``dict[str][str]``:: -Furthermore, type parameters are not checked by the Python interpreter during -object creation when using a generic type:: + >>> dict[str][str] + Traceback (most recent call last): + File "", line 1, in + TypeError: There are no type variables left in dict[str] + +However, that syntax is valid when type variables are used:: + + >>> from typing import TypeVar + >>> T = TypeVar('T') + >>> dict[str, T][int] + dict[str, int] - list[str]([1, 2, 3]) == list[int]([1, 2, 3]) -The following collections are generics. Most of their type parameters -can be found in the :mod:`typing` module: +Standard Generic Collections +---------------------------- + +These standard library collections support parameterized generics. Most of +their type parameters can be found in the :mod:`typing` module: * :class:`tuple` * :class:`list` @@ -4844,7 +4884,41 @@ can be found in the :mod:`typing` module: * :ref:`re.Pattern ` * :ref:`re.Match ` -The type for the ``GenericAlias`` object is :data:`types.GenericAlias`. + +Special Attributes of Generics +------------------------------ + +All parameterized generics implement special read-only attributes. + +.. attribute:: generic.__origin__ + + This attribute points at the non-parameterized generic class:: + + >>> list[int].__origin__ + + + +.. attribute:: generic.__args__ + + This attribute is a :class:`tuple` (possibly of length 1) of generic + types passed to the original :meth:`__class_getitem__` + of the generic container:: + + >>> dict[str, list[int]].__args__ + (, list[int]) + + +.. attribute:: generic.__parameters__ + + This attribute is a lazily computed tuple (possibly empty) of unique type + variables found in ``__args__``:: + + >>> from typing import TypeVar + >>> + >>> T = TypeVar('T') + >>> list[t].__parameters__ + (~T,) + .. seealso:: From 3bd13c2126d2a47554fd8d1cb1235a384df4ba57 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 18 Oct 2020 01:07:06 +0800 Subject: [PATCH 4/9] fix typos and minor tweaks --- Doc/library/stdtypes.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index b46f4fa849e20f..3d0709ce0cac16 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4763,7 +4763,7 @@ The ``GenericAlias`` object acts as a proxy for :term:`generic types `, implementing *parameterized generics* - a specific instance of a generic with the types for container elements provided. It is intended primarily for type :term:`annotations `. ``GenericAlias`` objects -are returned by expressions like ``list[int]``. +are created by expressions like ``list[int]``. The type for the ``GenericAlias`` object is :data:`types.GenericAlias`. @@ -4923,8 +4923,7 @@ All parameterized generics implement special read-only attributes. .. seealso:: * :pep:`585` -- "Type Hinting Generics In Standard Collections" - * :meth:`__class_getitem__` -- Method used to parameterize contained types. - in generics + * :meth:`__class_getitem__` -- Used to implement parameterized generics. .. versionadded:: 3.9 From ee3a16d6064f17970a29cb756475119d1f913be8 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 21 Oct 2020 00:24:53 +0800 Subject: [PATCH 5/9] add intro and a implementation --- Doc/library/stdtypes.rst | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 3d0709ce0cac16..093d763a3ba1f4 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4759,6 +4759,12 @@ Generic Alias Type object: GenericAlias pair: Generic; Alias +Most of the time, the :ref:`subscription expression ` calls the +:term:`method` :meth:`__getitem__` of an :term:`object`. However, the +subscription of a :term:`class` itself calls the :func:`classmethod +` :meth:`__class_getitem__` of the class instead. The classmethod +:meth:`__class_getitem__` returns a ``GenericAlias`` object. + The ``GenericAlias`` object acts as a proxy for :term:`generic types `, implementing *parameterized generics* - a specific instance of a generic with the types for container elements provided. It is intended @@ -4767,6 +4773,13 @@ are created by expressions like ``list[int]``. The type for the ``GenericAlias`` object is :data:`types.GenericAlias`. +.. impl-detail:: + + The C equivalent of :meth:`__getitem__` - :c:func:`PyObject_GetItem` - is + called first for builtin classes and types. When :c:func:`PyObject_GetItem` + detects that it was called on a type, it then calls :meth:`__class_getitem__` + and returns the ``GenericAlias`` object. + .. describe:: generic[X, Y, ...] Defines a generic containing elements of types *X*, *Y*, and more depending @@ -4885,12 +4898,12 @@ their type parameters can be found in the :mod:`typing` module: * :ref:`re.Match ` -Special Attributes of Generics ------------------------------- +Special Attributes of Generic Alias +----------------------------------- All parameterized generics implement special read-only attributes. -.. attribute:: generic.__origin__ +.. attribute:: genericalias.__origin__ This attribute points at the non-parameterized generic class:: @@ -4898,7 +4911,7 @@ All parameterized generics implement special read-only attributes. -.. attribute:: generic.__args__ +.. attribute:: genericalias.__args__ This attribute is a :class:`tuple` (possibly of length 1) of generic types passed to the original :meth:`__class_getitem__` @@ -4908,7 +4921,7 @@ All parameterized generics implement special read-only attributes. (, list[int]) -.. attribute:: generic.__parameters__ +.. attribute:: genericalias.__parameters__ This attribute is a lazily computed tuple (possibly empty) of unique type variables found in ``__args__``:: From 3258cfc3d7f2811262e9af2f07a8b8aa8994c686 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Mon, 26 Oct 2020 10:23:20 +0800 Subject: [PATCH 6/9] Implement suggestions --- Doc/library/stdtypes.rst | 76 ++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 093d763a3ba1f4..cda4be2e65e9d3 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4759,46 +4759,47 @@ Generic Alias Type object: GenericAlias pair: Generic; Alias -Most of the time, the :ref:`subscription expression ` calls the -:term:`method` :meth:`__getitem__` of an :term:`object`. However, the -subscription of a :term:`class` itself calls the :func:`classmethod -` :meth:`__class_getitem__` of the class instead. The classmethod -:meth:`__class_getitem__` returns a ``GenericAlias`` object. +Usually, the :ref:`subscription ` of builtin containers +objects calls the method :meth:`__getitem__` of the object. However, the +subscription of some builtin containers' classes may call the classmethod +:meth:`__class_getitem__` of the class instead. The classmethod +:meth:`__class_getitem__` returns a ``GenericAlias`` object. An example of this +is the expression ``list[int]``. + +.. note:: + When :meth:`__class_getitem__` of the class is not present, the + :meth:`__getitem__` is still called. The ``GenericAlias`` object acts as a proxy for :term:`generic types `, implementing *parameterized generics* - a specific instance -of a generic with the types for container elements provided. It is intended -primarily for type :term:`annotations `. ``GenericAlias`` objects -are created by expressions like ``list[int]``. +of a generic which provides the types for container elements. It is intended +primarily for :term:`type annotations `. -The type for the ``GenericAlias`` object is :data:`types.GenericAlias`. - -.. impl-detail:: +The user-exposed type for the ``GenericAlias`` object can be accessed from +:data:`types.GenericAlias` and used for :func:`isinstance` checks. - The C equivalent of :meth:`__getitem__` - :c:func:`PyObject_GetItem` - is - called first for builtin classes and types. When :c:func:`PyObject_GetItem` - detects that it was called on a type, it then calls :meth:`__class_getitem__` - and returns the ``GenericAlias`` object. +.. describe:: GenericType[X, Y, ...] -.. describe:: generic[X, Y, ...] - - Defines a generic containing elements of types *X*, *Y*, and more depending - on the *generic* used. For example, for a function expecting a :class:`list` - containing :class:`float` elements:: + Creates a ``GenericAlias`` representing a ``GenericType`` containing elements + of types *X*, *Y*, and more depending on the ``GenericType`` used. + For example, for a function expecting a :class:`list` containing + :class:`float` elements:: def average(values: list[float]) -> float: return sum(values) / len(values) - Another example for :term:`mapping` objects, using a :class:`dict`. In this - case, the function expects a ``dict`` for its ``body`` argument. The ``body`` - has keys of type :class:`str` and their corresponding values are lists which - hold :class:`int` elements:: + Another example for :term:`mapping` objects, using a :class:`dict`. A + :class:`dict` is a generic type expecting two type parameters representing + the key type and the value type. In this case, the function expects a + ``dict`` for its ``body`` argument. The ``body`` has keys of type + :class:`str` and their corresponding values are lists which hold :class:`int` + elements:: def send_post_request(url: str, body: dict[str, list[int]]) -> None: ... The builtin functions :func:`isinstance` and :func:`issubclass` do not accept -parameterized generic types for their second argument:: +``GenericAlias`` types for their second argument:: >>> isinstance([1, 2], list[str]) Traceback (most recent call last): @@ -4810,9 +4811,9 @@ parameterized generic types for their second argument:: File "", line 1, in TypeError: issubclass() argument 2 cannot be a parameterized generic -The Python runtime does not enforce type :term:`annotations `. +The Python runtime does not enforce :term:`type annotations `. This extends to generic types and their type parameters. When creating -an object from a parameterized generic, container elements are not checked +an object from a ``GenericAlias``, container elements are not checked against their type. For example, the following code is discouraged, but will run without errors:: @@ -4831,10 +4832,13 @@ creation:: >>> type(l) -Calling :func:`repr` on a generic shows the parameterized type:: +Calling :func:`repr` or :func:`str` on a generic shows the parameterized type:: >>> repr(list[int]) 'list[int]' + >>> + >>> str(list[int]) + 'list[int]' The :meth:`__getitem__` method of generics will raise an exception to disallow mistakes like ``dict[str][str]``:: @@ -4844,19 +4848,22 @@ mistakes like ``dict[str][str]``:: File "", line 1, in TypeError: There are no type variables left in dict[str] -However, that syntax is valid when type variables are used:: +However, that expression is valid when :ref:`type variables ` are +used. ``GenericAlias`` can only be indexed if it has type variables. The index +must have as many elements as there are type variable items in the +``GenericAlias`` object's :attr:`__args__ `. :: >>> from typing import TypeVar - >>> T = TypeVar('T') - >>> dict[str, T][int] + >>> X = TypeVar('X') + >>> Y = TypeVar('Y') + >>> dict[X, Y][str, int] dict[str, int] Standard Generic Collections ---------------------------- -These standard library collections support parameterized generics. Most of -their type parameters can be found in the :mod:`typing` module: +These standard library collections support parameterized generics. * :class:`tuple` * :class:`list` @@ -4929,7 +4936,7 @@ All parameterized generics implement special read-only attributes. >>> from typing import TypeVar >>> >>> T = TypeVar('T') - >>> list[t].__parameters__ + >>> list[T].__parameters__ (~T,) @@ -4937,6 +4944,7 @@ All parameterized generics implement special read-only attributes. * :pep:`585` -- "Type Hinting Generics In Standard Collections" * :meth:`__class_getitem__` -- Used to implement parameterized generics. + * :ref:`generics` -- Generics in the :mod:`typing` module. .. versionadded:: 3.9 From dffc2941c58b3a11e393ebb35193884a5e0f131e Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 27 Oct 2020 23:52:00 +0800 Subject: [PATCH 7/9] Implement second round of suggestions Co-Authored-By: Guido van Rossum --- Doc/library/stdtypes.rst | 72 +++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index cda4be2e65e9d3..b88b30a55525c4 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4759,43 +4759,57 @@ Generic Alias Type object: GenericAlias pair: Generic; Alias -Usually, the :ref:`subscription ` of builtin containers -objects calls the method :meth:`__getitem__` of the object. However, the -subscription of some builtin containers' classes may call the classmethod -:meth:`__class_getitem__` of the class instead. The classmethod -:meth:`__class_getitem__` returns a ``GenericAlias`` object. An example of this -is the expression ``list[int]``. +``GenericAlias`` objects are created by subscripting a class (usually a +container), such as ``list[int]``. They are intended primarily for +:term:`type annotations `. + +Usually, the :ref:`subscription ` of container objects calls the +method :meth:`__getitem__` of the object. However, the subscription of some +containers' classes may call the classmethod :meth:`__class_getitem__` of the +class instead. The classmethod :meth:`__class_getitem__` should return a +``GenericAlias`` object. .. note:: - When :meth:`__class_getitem__` of the class is not present, the - :meth:`__getitem__` is still called. + If the :meth:`__getitem__` of the class' metaclass is present, it will take + precedence over the :meth:`__class_getitem__` defined in the class (see + :pep:`560` for more details) :: + + >>> class M(type): + ... def __getitem__(self, key): + ... print('__getitem__ was called') + + >>> class T(metaclass=M): + ... def __class_getitem__(cls, key): + ... print('__class_getitem__ was called') + + >>> T[int] + '__getitem__ was called' + The ``GenericAlias`` object acts as a proxy for :term:`generic types `, implementing *parameterized generics* - a specific instance -of a generic which provides the types for container elements. It is intended -primarily for :term:`type annotations `. +of a generic which provides the types for container elements. The user-exposed type for the ``GenericAlias`` object can be accessed from :data:`types.GenericAlias` and used for :func:`isinstance` checks. -.. describe:: GenericType[X, Y, ...] +.. describe:: T[X, Y, ...] - Creates a ``GenericAlias`` representing a ``GenericType`` containing elements - of types *X*, *Y*, and more depending on the ``GenericType`` used. - For example, for a function expecting a :class:`list` containing + Creates a ``GenericAlias`` representing a type ``T`` containing elements + of types *X*, *Y*, and more depending on the ``T`` used. + For example, a function expecting a :class:`list` containing :class:`float` elements:: def average(values: list[float]) -> float: return sum(values) / len(values) - Another example for :term:`mapping` objects, using a :class:`dict`. A - :class:`dict` is a generic type expecting two type parameters representing - the key type and the value type. In this case, the function expects a - ``dict`` for its ``body`` argument. The ``body`` has keys of type - :class:`str` and their corresponding values are lists which hold :class:`int` - elements:: + Another example for :term:`mapping` objects, using a :class:`dict`, which + is a generic type expecting two type parameters representing the key type + and the value type. In this case, the function expects a ``dict`` for its + ``body`` argument. The ``body`` has keys of type :class:`str` and their + corresponding values are of type :class:`int`:: - def send_post_request(url: str, body: dict[str, list[int]]) -> None: + def send_post_request(url: str, body: dict[str, int]) -> None: ... The builtin functions :func:`isinstance` and :func:`issubclass` do not accept @@ -4805,7 +4819,7 @@ The builtin functions :func:`isinstance` and :func:`issubclass` do not accept Traceback (most recent call last): File "", line 1, in TypeError: isinstance() argument 2 cannot be a parameterized generic - >>> + >>> issubclass(list, list[str]) Traceback (most recent call last): File "", line 1, in @@ -4827,7 +4841,7 @@ creation:: >>> t = list[str] >>> type(t) - >>> + >>> l = t() >>> type(l) @@ -4836,7 +4850,7 @@ Calling :func:`repr` or :func:`str` on a generic shows the parameterized type:: >>> repr(list[int]) 'list[int]' - >>> + >>> str(list[int]) 'list[int]' @@ -4848,15 +4862,13 @@ mistakes like ``dict[str][str]``:: File "", line 1, in TypeError: There are no type variables left in dict[str] -However, that expression is valid when :ref:`type variables ` are -used. ``GenericAlias`` can only be indexed if it has type variables. The index -must have as many elements as there are type variable items in the -``GenericAlias`` object's :attr:`__args__ `. :: +However, such expressions are valid when :ref:`type variables ` are +used. The index must have as many elements as there are type variable items +in the ``GenericAlias`` object's :attr:`__args__ `. :: >>> from typing import TypeVar - >>> X = TypeVar('X') >>> Y = TypeVar('Y') - >>> dict[X, Y][str, int] + >>> dict[str, Y][int] dict[str, int] From 879365382b0b9d3968abb73f42fb0a9aff581977 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 28 Oct 2020 00:48:56 +0800 Subject: [PATCH 8/9] minor formatting nits --- Doc/library/stdtypes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index b88b30a55525c4..d778970ce11824 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4772,7 +4772,7 @@ class instead. The classmethod :meth:`__class_getitem__` should return a .. note:: If the :meth:`__getitem__` of the class' metaclass is present, it will take precedence over the :meth:`__class_getitem__` defined in the class (see - :pep:`560` for more details) :: + :pep:`560` for more details):: >>> class M(type): ... def __getitem__(self, key): @@ -4946,7 +4946,7 @@ All parameterized generics implement special read-only attributes. variables found in ``__args__``:: >>> from typing import TypeVar - >>> + >>> T = TypeVar('T') >>> list[T].__parameters__ (~T,) From e91c4adb66748acdc865d2fc62cfbce4fc6a4070 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 27 Oct 2020 10:38:14 -0700 Subject: [PATCH 9/9] Apply final suggestions from code review --- Doc/library/stdtypes.rst | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index d778970ce11824..07cc101d36dbb3 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4772,19 +4772,7 @@ class instead. The classmethod :meth:`__class_getitem__` should return a .. note:: If the :meth:`__getitem__` of the class' metaclass is present, it will take precedence over the :meth:`__class_getitem__` defined in the class (see - :pep:`560` for more details):: - - >>> class M(type): - ... def __getitem__(self, key): - ... print('__getitem__ was called') - - >>> class T(metaclass=M): - ... def __class_getitem__(cls, key): - ... print('__class_getitem__ was called') - - >>> T[int] - '__getitem__ was called' - + :pep:`560` for more details). The ``GenericAlias`` object acts as a proxy for :term:`generic types `, implementing *parameterized generics* - a specific instance @@ -4805,9 +4793,8 @@ The user-exposed type for the ``GenericAlias`` object can be accessed from Another example for :term:`mapping` objects, using a :class:`dict`, which is a generic type expecting two type parameters representing the key type - and the value type. In this case, the function expects a ``dict`` for its - ``body`` argument. The ``body`` has keys of type :class:`str` and their - corresponding values are of type :class:`int`:: + and the value type. In this example, the function expects a ``dict`` with + keys of type :class:`str` and values of type :class:`int`:: def send_post_request(url: str, body: dict[str, int]) -> None: ... @@ -4820,11 +4807,6 @@ The builtin functions :func:`isinstance` and :func:`issubclass` do not accept File "", line 1, in TypeError: isinstance() argument 2 cannot be a parameterized generic - >>> issubclass(list, list[str]) - Traceback (most recent call last): - File "", line 1, in - TypeError: issubclass() argument 2 cannot be a parameterized generic - The Python runtime does not enforce :term:`type annotations `. This extends to generic types and their type parameters. When creating an object from a ``GenericAlias``, container elements are not checked