mirror of
https://github.com/python/cpython.git
synced 2025-12-15 21:44:50 +00:00
gh-119180: Documentation for PEP 649 and 749 (#122235)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
This commit is contained in:
parent
6e23c89fcd
commit
5436d8b9c3
11 changed files with 680 additions and 104 deletions
|
|
@ -1329,13 +1329,7 @@ following the parameter name. Any parameter may have an annotation, even those
|
|||
``*identifier`` or ``**identifier``. Functions may have "return" annotation of
|
||||
the form "``-> expression``" after the parameter list. These annotations can be
|
||||
any valid Python expression. The presence of annotations does not change the
|
||||
semantics of a function. The annotation values are available as values of
|
||||
a dictionary keyed by the parameters' names in the :attr:`__annotations__`
|
||||
attribute of the function object. If the ``annotations`` import from
|
||||
:mod:`__future__` is used, annotations are preserved as strings at runtime which
|
||||
enables postponed evaluation. Otherwise, they are evaluated when the function
|
||||
definition is executed. In this case annotations may be evaluated in
|
||||
a different order than they appear in the source code.
|
||||
semantics of a function. See :ref:`annotations` for more information on annotations.
|
||||
|
||||
.. index:: pair: lambda; expression
|
||||
|
||||
|
|
@ -1852,6 +1846,44 @@ Here, ``annotation-def`` (not a real keyword) indicates an
|
|||
:ref:`annotation scope <annotation-scopes>`. The capitalized names
|
||||
like ``TYPE_PARAMS_OF_ListOrSet`` are not actually bound at runtime.
|
||||
|
||||
.. _annotations:
|
||||
|
||||
Annotations
|
||||
===========
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotations are now lazily evaluated by default.
|
||||
|
||||
Variables and function parameters may carry :term:`annotations <annotation>`,
|
||||
created by adding a colon after the name, followed by an expression::
|
||||
|
||||
x: annotation = 1
|
||||
def f(param: annotation): ...
|
||||
|
||||
Functions may also carry a return annotation following an arrow::
|
||||
|
||||
def f() -> annotation: ...
|
||||
|
||||
Annotations are conventionally used for :term:`type hints <type hint>`, but this
|
||||
is not enforced by the language, and in general annotations may contain arbitrary
|
||||
expressions. The presence of annotations does not change the runtime semantics of
|
||||
the code, except if some mechanism is used that introspects and uses the annotations
|
||||
(such as :mod:`dataclasses` or :func:`functools.singledispatch`).
|
||||
|
||||
By default, annotations are lazily evaluated in a :ref:`annotation scope <annotation-scopes>`.
|
||||
This means that they are not evaluated when the code containing the annotation is evaluated.
|
||||
Instead, the interpreter saves information that can be used to evaluate the annotation later
|
||||
if requested. The :mod:`annotationlib` module provides tools for evaluating annotations.
|
||||
|
||||
If the :ref:`future statement <future>` ``from __future__ import annotations`` is present,
|
||||
all annotations are instead stored as strings::
|
||||
|
||||
>>> from __future__ import annotations
|
||||
>>> def f(param: annotation): ...
|
||||
>>> f.__annotations__
|
||||
{'param': 'annotation'}
|
||||
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#] The exception is propagated to the invocation stack unless
|
||||
|
|
|
|||
|
|
@ -581,6 +581,7 @@ Special writable attributes
|
|||
single: __defaults__ (function attribute)
|
||||
single: __code__ (function attribute)
|
||||
single: __annotations__ (function attribute)
|
||||
single: __annotate__ (function attribute)
|
||||
single: __kwdefaults__ (function attribute)
|
||||
single: __type_params__ (function attribute)
|
||||
|
||||
|
|
@ -628,7 +629,17 @@ Most of these attributes check the type of the assigned value:
|
|||
:term:`parameters <parameter>`.
|
||||
The keys of the dictionary are the parameter names,
|
||||
and ``'return'`` for the return annotation, if provided.
|
||||
See also: :ref:`annotations-howto`.
|
||||
See also: :attr:`object.__annotations__`.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotations are now :ref:`lazily evaluated <lazy-evaluation>`.
|
||||
See :pep:`649`.
|
||||
|
||||
* - .. attribute:: function.__annotate__
|
||||
- The :term:`annotate function` for this function, or ``None``
|
||||
if the function has no annotations. See :attr:`object.__annotate__`.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
* - .. attribute:: function.__kwdefaults__
|
||||
- A :class:`dictionary <dict>` containing defaults for keyword-only
|
||||
|
|
@ -881,6 +892,7 @@ Attribute assignment updates the module's namespace dictionary, e.g.,
|
|||
single: __doc__ (module attribute)
|
||||
single: __file__ (module attribute)
|
||||
single: __annotations__ (module attribute)
|
||||
single: __annotate__ (module attribute)
|
||||
pair: module; namespace
|
||||
|
||||
Predefined (writable) attributes:
|
||||
|
|
@ -901,11 +913,21 @@ Predefined (writable) attributes:
|
|||
loaded dynamically from a shared library, it's the pathname of the shared
|
||||
library file.
|
||||
|
||||
:attr:`__annotations__`
|
||||
:attr:`~object.__annotations__`
|
||||
A dictionary containing
|
||||
:term:`variable annotations <variable annotation>` collected during
|
||||
module body execution. For best practices on working
|
||||
with :attr:`__annotations__`, please see :ref:`annotations-howto`.
|
||||
with :attr:`!__annotations__`, see :mod:`annotationlib`.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotations are now :ref:`lazily evaluated <lazy-evaluation>`.
|
||||
See :pep:`649`.
|
||||
|
||||
:attr:`~object.__annotate__`
|
||||
The :term:`annotate function` for this module, or ``None``
|
||||
if the module has no annotations. See :attr:`object.__annotate__`.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. index:: single: __dict__ (module attribute)
|
||||
|
||||
|
|
@ -969,6 +991,7 @@ A class object can be called (see above) to yield a class instance (see below).
|
|||
single: __bases__ (class attribute)
|
||||
single: __doc__ (class attribute)
|
||||
single: __annotations__ (class attribute)
|
||||
single: __annotate__ (class attribute)
|
||||
single: __type_params__ (class attribute)
|
||||
single: __static_attributes__ (class attribute)
|
||||
single: __firstlineno__ (class attribute)
|
||||
|
|
@ -991,12 +1014,36 @@ Special attributes:
|
|||
:attr:`__doc__`
|
||||
The class's documentation string, or ``None`` if undefined.
|
||||
|
||||
:attr:`__annotations__`
|
||||
:attr:`~object.__annotations__`
|
||||
A dictionary containing
|
||||
:term:`variable annotations <variable annotation>`
|
||||
collected during class body execution. For best practices on
|
||||
working with :attr:`__annotations__`, please see
|
||||
:ref:`annotations-howto`.
|
||||
working with :attr:`~object.__annotations__`, please see
|
||||
:mod:`annotationlib`.
|
||||
|
||||
.. warning::
|
||||
|
||||
Accessing the :attr:`~object.__annotations__` attribute of a class
|
||||
object directly may yield incorrect results in the presence of
|
||||
metaclasses. Use :func:`annotationlib.get_annotations` to
|
||||
retrieve class annotations safely.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotations are now :ref:`lazily evaluated <lazy-evaluation>`.
|
||||
See :pep:`649`.
|
||||
|
||||
:attr:`~object.__annotate__`
|
||||
The :term:`annotate function` for this class, or ``None``
|
||||
if the class has no annotations. See :attr:`object.__annotate__`.
|
||||
|
||||
.. warning::
|
||||
|
||||
Accessing the :attr:`~object.__annotate__` attribute of a class
|
||||
object directly may yield incorrect results in the presence of
|
||||
metaclasses. Use :func:`annotationlib.get_annotate_function` to
|
||||
retrieve the annotate function safely.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
:attr:`__type_params__`
|
||||
A tuple containing the :ref:`type parameters <type-params>` of
|
||||
|
|
@ -3253,6 +3300,51 @@ implement the protocol in Python.
|
|||
:class:`collections.abc.Buffer`
|
||||
ABC for buffer types.
|
||||
|
||||
Annotations
|
||||
-----------
|
||||
|
||||
Functions, classes, and modules may contain :term:`annotations <annotation>`,
|
||||
which are a way to associate information (usually :term:`type hints <type hint>`)
|
||||
with a symbol.
|
||||
|
||||
.. attribute:: object.__annotations__
|
||||
|
||||
This attribute contains the annotations for an object. It is
|
||||
:ref:`lazily evaluated <lazy-evaluation>`, so accessing the attribute may
|
||||
execute arbitrary code and raise exceptions. If evaluation is successful, the
|
||||
attribute is set to a dictionary mapping from variable names to annotations.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotations are now lazily evaluated.
|
||||
|
||||
.. method:: object.__annotate__(format)
|
||||
|
||||
An :term:`annotate function`.
|
||||
Returns a new dictionary object mapping attribute/parameter names to their annotation values.
|
||||
|
||||
Takes a format parameter specifying the format in which annotations values should be provided.
|
||||
It must be a member of the :class:`annotationlib.Format` enum, or an integer with
|
||||
a value corresponding to a member of the enum.
|
||||
|
||||
If an annotate function doesn't support the requested format, it must raise
|
||||
:exc:`NotImplementedError`. Annotate functions must always support
|
||||
:attr:`~annotationlib.Format.VALUE` format; they must not raise
|
||||
:exc:`NotImplementedError()` when called with this format.
|
||||
|
||||
When called with :attr:`~annotationlib.Format.VALUE` format, an annotate function may raise
|
||||
:exc:`NameError`; it must not raise :exc:`!NameError` when called requesting any other format.
|
||||
|
||||
If an object does not have any annotations, :attr:`~object.__annotate__` should preferably be set
|
||||
to ``None`` (it can’t be deleted), rather than set to a function that returns an empty dict.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. seealso::
|
||||
|
||||
:pep:`649` --- Deferred evaluation of annotation using descriptors
|
||||
Introduces lazy evaluation of annotations and the ``__annotate__`` function.
|
||||
|
||||
|
||||
.. _special-lookup:
|
||||
|
||||
Special method lookup
|
||||
|
|
|
|||
|
|
@ -190,14 +190,15 @@ However, the following will succeed::
|
|||
Annotation scopes
|
||||
-----------------
|
||||
|
||||
:ref:`Type parameter lists <type-params>` and :keyword:`type` statements
|
||||
:term:`Annotations <annotation>`, :ref:`type parameter lists <type-params>`
|
||||
and :keyword:`type` statements
|
||||
introduce *annotation scopes*, which behave mostly like function scopes,
|
||||
but with some exceptions discussed below. :term:`Annotations <annotation>`
|
||||
currently do not use annotation scopes, but they are expected to use
|
||||
annotation scopes in Python 3.13 when :pep:`649` is implemented.
|
||||
but with some exceptions discussed below.
|
||||
|
||||
Annotation scopes are used in the following contexts:
|
||||
|
||||
* :term:`Function annotations <function annotation>`.
|
||||
* :term:`Variable annotations <variable annotation>`.
|
||||
* Type parameter lists for :ref:`generic type aliases <generic-type-aliases>`.
|
||||
* Type parameter lists for :ref:`generic functions <generic-functions>`.
|
||||
A generic function's annotations are
|
||||
|
|
@ -236,17 +237,23 @@ Annotation scopes differ from function scopes in the following ways:
|
|||
Annotation scopes are also used for type parameter defaults, as
|
||||
introduced by :pep:`696`.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotation scopes are now also used for annotations, as specified in
|
||||
:pep:`649` and :pep:`749`.
|
||||
|
||||
.. _lazy-evaluation:
|
||||
|
||||
Lazy evaluation
|
||||
---------------
|
||||
|
||||
The values of type aliases created through the :keyword:`type` statement are
|
||||
*lazily evaluated*. The same applies to the bounds, constraints, and default values of type
|
||||
Most annotation scopes are *lazily evaluated*. This includes annotations,
|
||||
the values of type aliases created through the :keyword:`type` statement, and
|
||||
the bounds, constraints, and default values of type
|
||||
variables created through the :ref:`type parameter syntax <type-params>`.
|
||||
This means that they are not evaluated when the type alias or type variable is
|
||||
created. Instead, they are only evaluated when doing so is necessary to resolve
|
||||
an attribute access.
|
||||
created, or when the object carrying annotations is created. Instead, they
|
||||
are only evaluated when necessary, for example when the ``__value__``
|
||||
attribute on a type alias is accessed.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
|||
|
|
@ -336,23 +336,21 @@ The difference from normal :ref:`assignment` is that only a single target is all
|
|||
The assignment target is considered "simple" if it consists of a single
|
||||
name that is not enclosed in parentheses.
|
||||
For simple assignment targets, if in class or module scope,
|
||||
the annotations are evaluated and stored in a special class or module
|
||||
attribute :attr:`__annotations__`
|
||||
that is a dictionary mapping from variable names (mangled if private) to
|
||||
evaluated annotations. This attribute is writable and is automatically
|
||||
created at the start of class or module body execution, if annotations
|
||||
are found statically.
|
||||
the annotations are gathered in a lazily evaluated
|
||||
:ref:`annotation scope <annotation-scopes>`. The annotations can be
|
||||
evaluated using the :attr:`~object.__annotations__` attribute of a
|
||||
class or module, or using the facilities in the :mod:`annotationlib`
|
||||
module.
|
||||
|
||||
If the assignment target is not simple (an attribute, subscript node, or
|
||||
parenthesized name), the annotation is evaluated if
|
||||
in class or module scope, but not stored.
|
||||
parenthesized name), the annotation is never evaluated.
|
||||
|
||||
If a name is annotated in a function scope, then this name is local for
|
||||
that scope. Annotations are never evaluated and stored in function scopes.
|
||||
|
||||
If the right hand side is present, an annotated
|
||||
assignment performs the actual assignment before evaluating annotations
|
||||
(where applicable). If the right hand side is not present for an expression
|
||||
assignment performs the actual assignment as if there was no annotation
|
||||
present. If the right hand side is not present for an expression
|
||||
target, then the interpreter evaluates the target except for the last
|
||||
:meth:`~object.__setitem__` or :meth:`~object.__setattr__` call.
|
||||
|
||||
|
|
@ -373,6 +371,10 @@ target, then the interpreter evaluates the target except for the last
|
|||
regular assignments. Previously, some expressions (like un-parenthesized
|
||||
tuple expressions) caused a syntax error.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Annotations are now lazily evaluated in a separate :ref:`annotation scope <annotation-scopes>`.
|
||||
If the assignment target is not simple, annotations are never evaluated.
|
||||
|
||||
|
||||
.. _assert:
|
||||
|
||||
|
|
@ -975,8 +977,8 @@ block textually preceding that :keyword:`!global` statement.
|
|||
|
||||
Names listed in a :keyword:`global` statement must not be defined as formal
|
||||
parameters, or as targets in :keyword:`with` statements or :keyword:`except` clauses, or in a :keyword:`for` target list, :keyword:`class`
|
||||
definition, function definition, :keyword:`import` statement, or variable
|
||||
annotation.
|
||||
definition, function definition, :keyword:`import` statement, or
|
||||
:term:`variable annotations <variable annotation>`.
|
||||
|
||||
.. impl-detail::
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue