-
-
Notifications
You must be signed in to change notification settings - Fork 31k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-45680: Clarify documentation on GenericAlias
objects
#29335
Changes from 7 commits
a6fe738
cef0930
614fce5
74269b8
671579b
d367338
d945e06
629a29d
5dd309c
5dbccad
bc457dd
d398971
a195216
af257a6
eb7e7be
5c8fe0d
010ca86
682cd6d
92e0463
dd3369e
6e2d8f5
43f9429
ba2af17
2776b8d
f2efd8b
ec8a509
8fad702
e5a57e8
ae21ffe
3944e8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4810,7 +4810,7 @@ Type Annotation Types --- :ref:`Generic Alias <types-genericalias>`, :ref:`Union | |
single: annotation; type annotation; type hint | ||
|
||
The core built-in types for :term:`type annotations <annotation>` are | ||
:ref:`Generic Alias <types-genericalias>` and :ref:`Union <types-union>`. | ||
:ref:`types-genericalias` and :ref:`types-union`. | ||
|
||
|
||
.. _types-genericalias: | ||
|
@@ -4822,35 +4822,51 @@ Generic Alias Type | |
object: GenericAlias | ||
pair: Generic; Alias | ||
|
||
``GenericAlias`` objects are created by subscripting a class (usually a | ||
container), such as ``list[int]``. They are intended primarily for | ||
``GenericAlias`` objects are generally created by | ||
:ref:`subscripting<subscriptions>` a class. They are most often used with | ||
:ref:`container classes<sequence-types>`, such as :class:`list` or | ||
:class:`dict`. For example, ``list[int]`` is a ``GenericAlias`` object created | ||
by subscripting the :class:`list` class with the argument :class:`int`. | ||
``GenericAlias`` objects are intended primarily for use with | ||
:term:`type annotations <annotation>`. | ||
|
||
Usually, the :ref:`subscription <subscriptions>` 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:: | ||
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). | ||
Comment on lines
-4829
to
-4838
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This material has been moved to the docs for |
||
|
||
The ``GenericAlias`` object acts as a proxy for :term:`generic types | ||
<generic type>`, implementing *parameterized generics* - a specific instance | ||
of a generic which provides the types for container elements. | ||
|
||
The user-exposed type for the ``GenericAlias`` object can be accessed from | ||
:class:`types.GenericAlias` and used for :func:`isinstance` checks. It can | ||
also be used to create ``GenericAlias`` objects directly. | ||
It is generally only possible to subscript a class if the class implements | ||
the special method :meth:`~object.__class_getitem__` | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
A ``GenericAlias`` object acts as a proxy for a :term:`generic type`, | ||
implementing *parameterized generics*. | ||
|
||
For a container class which implements :meth:`~object.__class_getitem__`, the | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
argument(s) supplied to a :ref:`subscription<subscriptions>` of the class may | ||
indicate the type(s) of the elements an object contains. For example, | ||
``set[bytes]`` can be used in type annotations to signify a :class:`set` in | ||
which all the elements are of type :class:`bytes`. | ||
|
||
For a class which defines :meth:`~object.__class_getitem__` but is not a | ||
container, the argument(s) supplied to a subscription of the class will often | ||
indicate the return type(s) of one or more methods defined on an object. For | ||
example, :mod:`regular expressions<re>` can be used on the :class:`str` data | ||
type and the :class:`bytes` data type. If ``x = re.search('foo', 'foo')``, | ||
``x`` will be a :ref:`re.Match <match-objects>` object where the return values | ||
of ``x.group(0)`` and ``x[0]`` will both be of type :class:`str`. We can | ||
represent this kind of object in type annotations with the ``GenericAlias`` | ||
``re.Match[str]``. If ``y = re.search(b'bar', b'bar')``, however, ``y`` will | ||
also be an instance of ``re.Match``, but the return values of ``y.group(0)`` | ||
and ``y[0]`` will both be of type :class:`bytes`. In type annotations, we would | ||
represent this subtype of :ref:`re.Match <match-objects>` with | ||
``re.Match[bytes]``. | ||
|
||
``GenericAlias`` objects are instances of the class | ||
:class:`types.GenericAlias`, which can also be used to create ``GenericAlias`` | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
objects directly. | ||
|
||
.. describe:: T[X, Y, ...] | ||
|
||
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:: | ||
Creates a ``GenericAlias`` representing a type ``T`` parameterized by 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) | ||
|
@@ -4900,8 +4916,8 @@ Calling :func:`repr` or :func:`str` on a generic shows the parameterized type:: | |
>>> str(list[int]) | ||
'list[int]' | ||
|
||
The :meth:`__getitem__` method of generics will raise an exception to disallow | ||
mistakes like ``dict[str][str]``:: | ||
The :meth:`~object.__getitem__` method of generics will raise an exception to | ||
disallow mistakes like ``dict[str][str]``:: | ||
|
||
>>> dict[str][str] | ||
Traceback (most recent call last): | ||
|
@@ -4910,18 +4926,19 @@ mistakes like ``dict[str][str]``:: | |
|
||
However, such expressions are valid when :ref:`type variables <generics>` are | ||
used. The index must have as many elements as there are type variable items | ||
in the ``GenericAlias`` object's :attr:`__args__ <genericalias.__args__>`. :: | ||
in the ``GenericAlias`` object's :attr:`~genericalias.__args__`. :: | ||
|
||
>>> from typing import TypeVar | ||
>>> Y = TypeVar('Y') | ||
>>> dict[str, Y][int] | ||
dict[str, int] | ||
|
||
|
||
Standard Generic Collections | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
Standard Generic Classes | ||
^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
These standard library collections support parameterized generics. | ||
The following standard library classes support parameterized generics. This | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was discussion on the previous PR that I opened on how to introduce this list. @ambv suggested "The following standard library data structures [...]" — I've gone for "The following standard library classes [...]" as I think the definition of "class" is probably easier to grok than the definition of "data structure". |
||
list is non-exhaustive. | ||
|
||
* :class:`tuple` | ||
* :class:`list` | ||
|
@@ -4959,12 +4976,33 @@ These standard library collections support parameterized generics. | |
* :class:`collections.abc.ValuesView` | ||
* :class:`contextlib.AbstractContextManager` | ||
* :class:`contextlib.AbstractAsyncContextManager` | ||
* :class:`dataclasses.Field` | ||
* :class:`functools.cached_property` | ||
* :class:`functools.partialmethod` | ||
* :class:`os.PathLike` | ||
* :class:`pathlib.Path` | ||
* :class:`pathlib.PurePath` | ||
* :class:`pathlib.PurePosixPath` | ||
* :class:`pathlib.PureWindowsPath` | ||
* :class:`queue.LifoQueue` | ||
* :class:`queue.Queue` | ||
* :class:`queue.PriorityQueue` | ||
* :class:`queue.SimpleQueue` | ||
* :ref:`re.Pattern <re-objects>` | ||
* :ref:`re.Match <match-objects>` | ||
* :class:`shelve.BsdDbShelf` | ||
* :class:`shelve.DbfilenameShelf` | ||
* :class:`shelve.Shelf` | ||
* :class:`types.MappingProxyType` | ||
* :class:`weakref.WeakKeyDictionary` | ||
* :class:`weakref.WeakMethod` | ||
* :class:`weakref.WeakSet` | ||
* :class:`weakref.WeakValueDictionary` | ||
|
||
|
||
|
||
Special Attributes of Generic Alias | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
Special Attributes of ``GenericAlias`` objects | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
All parameterized generics implement special read-only attributes. | ||
|
||
|
@@ -4979,8 +5017,8 @@ All parameterized generics implement special read-only attributes. | |
.. attribute:: genericalias.__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:: | ||
types passed to the original :meth:`~object.__class_getitem__` of the | ||
generic container:: | ||
|
||
>>> dict[str, list[int]].__args__ | ||
(<class 'str'>, list[int]) | ||
|
@@ -4999,14 +5037,15 @@ All parameterized generics implement special read-only attributes. | |
|
||
|
||
.. note:: | ||
A ``GenericAlias`` object with :class:`typing.ParamSpec` parameters may not | ||
have correct ``__parameters__`` after substitution because | ||
A ``GenericAlias`` object with :class:`typing.ParamSpec` parameters may | ||
not have correct ``__parameters__`` after substitution because | ||
:class:`typing.ParamSpec` is intended primarily for static type checking. | ||
|
||
.. seealso:: | ||
|
||
* :pep:`585` -- "Type Hinting Generics In Standard Collections" | ||
* :meth:`__class_getitem__` -- Used to implement parameterized generics. | ||
* :meth:`~object.__class_getitem__` -- Used to implement parameterized | ||
generics. | ||
* :ref:`generics` -- Generics in the :mod:`typing` module. | ||
|
||
.. versionadded:: 3.9 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Amend the docs on ``GenericAlias`` objects to clarify that non-container | ||
classes can also implement ``__class_getitem__``. Patch contributed by Alex | ||
Waygood. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the wording from "are created by subscripting a class" to "are generally created by subscripting a class". This is because it is certainly possible to directly instantiate a
GenericAlias
object throughtypes.GenericAlias
, as this documentation states later on.