Skip to content
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

Merged
merged 30 commits into from
Jan 19, 2022
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a6fe738
bpo-45680: Clarify documentation on ``GenericAlias`` objects
AlexWaygood Oct 30, 2021
cef0930
Correct typo
AlexWaygood Oct 30, 2021
614fce5
Add more `shelve` classes
AlexWaygood Oct 31, 2021
74269b8
Remove brackets
AlexWaygood Nov 1, 2021
671579b
Add link to container classes, remove use of the word 'they'
AlexWaygood Nov 1, 2021
d367338
Improve cross-references to data model docs
AlexWaygood Nov 2, 2021
d945e06
Move example to ``__class_getitem__`` docs in the data model
AlexWaygood Nov 2, 2021
629a29d
revert line 4813
AlexWaygood Nov 2, 2021
5dd309c
More instances where it is implied that only containers can be parame…
AlexWaygood Nov 2, 2021
5dbccad
Improve references in glossary and typing docs
AlexWaygood Nov 2, 2021
bc457dd
Fix typing docs link to ``__class_getitem__`` method
AlexWaygood Nov 2, 2021
d398971
Add note about ``typing.Generic``
AlexWaygood Nov 2, 2021
a195216
Merge branch 'generic-alias-docs' of https://github.com/AlexWaygood/c…
AlexWaygood Nov 2, 2021
af257a6
Update glossary
AlexWaygood Nov 18, 2021
eb7e7be
Update typing
AlexWaygood Nov 18, 2021
5c8fe0d
update datamodel
AlexWaygood Nov 18, 2021
010ca86
delete news
AlexWaygood Nov 18, 2021
682cd6d
Merge remote-tracking branch 'origin/main' into generic-alias-docs
AlexWaygood Nov 18, 2021
92e0463
A few tweaks
AlexWaygood Nov 19, 2021
dd3369e
Add full stop.
AlexWaygood Nov 19, 2021
6e2d8f5
Remove redundant clause.
AlexWaygood Nov 19, 2021
43f9429
Update Doc/library/stdtypes.rst
AlexWaygood Nov 19, 2021
ba2af17
Reduce diff
AlexWaygood Nov 29, 2021
2776b8d
Trailing whitespace
AlexWaygood Nov 29, 2021
f2efd8b
Update Doc/library/stdtypes.rst
AlexWaygood Dec 4, 2021
ec8a509
Fix CI
AlexWaygood Dec 4, 2021
8fad702
Improve markup readability
AlexWaygood Dec 5, 2021
e5a57e8
Steer clear of the word "subtype"
AlexWaygood Dec 5, 2021
ae21ffe
Tweak
AlexWaygood Dec 5, 2021
3944e8c
Apply formatting suggestions from code review
Fidget-Spinner Jan 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 84 additions & 33 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4822,33 +4822,54 @@ 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
Copy link
Member Author

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 through types.GenericAlias, as this documentation states later on.

:ref:`subscripting <subscriptions>` a class. They are most often used with
:ref:`container classes <sequence-types>`, such as :class:`list` or
AlexWaygood marked this conversation as resolved.
Show resolved Hide resolved
:class:`dict`. For example, ``list[int]`` is a ``GenericAlias`` object created
by subscripting the ``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
Copy link
Member Author

@AlexWaygood AlexWaygood Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This material has been moved to the docs for __class_getitem__ in the data model, per @Fidget-Spinner's suggestion (see #29389)


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.
It is generally only possible to subscript a class if the class implements
the special method :meth:`~object.__class_getitem__`.

A ``GenericAlias`` object acts as a proxy for a :term:`generic type`,
implementing *parameterized generics*.

For a container class, the
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 both 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
Fidget-Spinner marked this conversation as resolved.
Show resolved Hide resolved
represent this kind of object in type annotations with the ``GenericAlias``
``re.Match[str]``.

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.
* If ``y = re.search(b'bar', b'bar')``, (note the ``b`` for :class:`bytes`),
``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
variety of :ref:`re.Match <match-objects>` 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.
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::

Expand All @@ -4873,7 +4894,7 @@ The builtin functions :func:`isinstance` and :func:`issubclass` do not accept

The Python runtime does not enforce :term:`type annotations <annotation>`.
This extends to generic types and their type parameters. When creating
an object from a ``GenericAlias``, container elements are not checked
a container object from a ``GenericAlias``, the elements in the container are not checked
against their type. For example, the following code is discouraged, but will
run without errors::

Expand All @@ -4900,8 +4921,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 generic containers will raise an
exception to disallow mistakes like ``dict[str][str]``::

>>> dict[str][str]
Traceback (most recent call last):
Expand All @@ -4910,18 +4931,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
Copy link
Member Author

@AlexWaygood AlexWaygood Nov 1, 2021

Choose a reason for hiding this comment

The 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`
Expand Down Expand Up @@ -4959,12 +4981,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.

Expand All @@ -4979,8 +5022,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 class::

>>> dict[str, list[int]].__args__
(<class 'str'>, list[int])
Expand All @@ -5005,9 +5048,17 @@ All parameterized generics implement special read-only attributes.

.. seealso::

* :pep:`585` -- "Type Hinting Generics In Standard Collections"
* :meth:`__class_getitem__` -- Used to implement parameterized generics.
* :ref:`generics` -- Generics in the :mod:`typing` module.
:pep:`484` - Type Hints
Introducing Python's framework for type annotations.

:pep:`585` - "Type Hinting Generics In Standard Collections"
Fidget-Spinner marked this conversation as resolved.
Show resolved Hide resolved
Introducing the ability to natively parameterize standard-library
classes, provided they implement the special class method
:meth:`~object.__class_getitem__`.

:ref:`Generics`, :ref:`user-defined generics <user-defined-generics>` and :class:`typing.Generic`
Documentation on how to implement generic classes that can be
parameterized at runtime and understood by static type-checkers.

.. versionadded:: 3.9

Expand Down