Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
7 changes: 7 additions & 0 deletions Doc/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <type hint>` and
:term:`annotations <annotation>`.

See :pep:`483` for more details, and :mod:`typing` or
:ref:`generic alias type <types-genericalias>` for its uses.

GIL
See :term:`global interpreter lock`.
Expand Down
200 changes: 200 additions & 0 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4749,6 +4749,206 @@ 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

Usually, the :ref:`subscription <subscriptions>` of builtin containers
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated
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]``.
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated

.. note::
When :meth:`__class_getitem__` of the class is not present, the
:meth:`__getitem__` is still called.
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated

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 intended
primarily for :term:`type annotations <annotation>`.

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, ...]
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated

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`. A
:class:`dict` is a generic type expecting two type parameters representing
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated
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::
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated

def send_post_request(url: str, body: dict[str, list[int]]) -> None:
...

The builtin functions :func:`isinstance` and :func:`issubclass` do not accept
``GenericAlias`` types for their second argument::

>>> isinstance([1, 2], list[str])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() argument 2 cannot be a parameterized generic
>>>
>>> issubclass(list, list[str])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: issubclass() argument 2 cannot be a parameterized generic

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
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)
<class 'types.GenericAlias'>
>>>
>>> l = t()
>>> type(l)
<class 'list'>

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]``::

>>> dict[str][str]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: There are no type variables left in dict[str]

However, that expression is valid when :ref:`type variables <generics>` are
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated
used. ``GenericAlias`` can only be indexed if it has type variables. The index
Comment thread
Fidget-Spinner marked this conversation as resolved.
Outdated
must have as many elements as there are type variable items in the
``GenericAlias`` object's :attr:`__args__ <genericalias.__args__>`. ::

>>> from typing import TypeVar
>>> X = TypeVar('X')
>>> Y = TypeVar('Y')
>>> dict[X, Y][str, int]
dict[str, int]


Standard Generic Collections
----------------------------

These standard library collections support parameterized generics.

* :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 <re-objects>`
* :ref:`re.Match <match-objects>`


Special Attributes of Generic Alias
-----------------------------------

All parameterized generics implement special read-only attributes.

.. attribute:: genericalias.__origin__

This attribute points at the non-parameterized generic class::

>>> list[int].__origin__
<class 'list'>


.. 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::

>>> dict[str, list[int]].__args__
(<class 'str'>, list[int])


.. attribute:: genericalias.__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::
Comment thread
Fidget-Spinner marked this conversation as resolved.

* :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


.. _types-union:

Union Type
Expand Down
7 changes: 7 additions & 0 deletions Doc/library/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ Standard names are defined for the following types:

.. versionadded:: 3.10

.. data:: GenericAlias

The type of :ref:`parameterized generics <types-genericalias>` such as
``list[int]``.

.. versionadded:: 3.9

.. data:: Union

The type of :ref:`union type expressions<types-union>`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Documented :ref:`generic alias type <types-genericalias>` and
:data:`types.GenericAlias`. Also added an entry in glossary for
:term:`generic types <generic type>`.