mirror of https://github.com/python/cpython
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
|
@ -36,6 +36,12 @@ Glossary
|
|||
and loaders (in the :mod:`importlib.abc` module). You can create your own
|
||||
ABCs with the :mod:`abc` module.
|
||||
|
||||
annotate function
|
||||
A function that can be called to retrieve the :term:`annotations <annotation>`
|
||||
of an object. This function is accessible as the :attr:`~object.__annotate__`
|
||||
attribute of functions, classes, and modules. Annotate functions are a
|
||||
subset of :term:`evaluate functions <evaluate function>`.
|
||||
|
||||
annotation
|
||||
A label associated with a variable, a class
|
||||
attribute or a function parameter or return value,
|
||||
|
@ -43,12 +49,11 @@ Glossary
|
|||
|
||||
Annotations of local variables cannot be accessed at runtime, but
|
||||
annotations of global variables, class attributes, and functions
|
||||
are stored in the :attr:`__annotations__`
|
||||
special attribute of modules, classes, and functions,
|
||||
respectively.
|
||||
can be retrieved by calling :func:`annotationlib.get_annotations`
|
||||
on modules, classes, and functions, respectively.
|
||||
|
||||
See :term:`variable annotation`, :term:`function annotation`, :pep:`484`
|
||||
and :pep:`526`, which describe this functionality.
|
||||
See :term:`variable annotation`, :term:`function annotation`, :pep:`484`,
|
||||
:pep:`526`, and :pep:`649`, which describe this functionality.
|
||||
Also see :ref:`annotations-howto`
|
||||
for best practices on working with annotations.
|
||||
|
||||
|
@ -366,6 +371,11 @@ Glossary
|
|||
statements. The technique contrasts with the :term:`LBYL` style
|
||||
common to many other languages such as C.
|
||||
|
||||
evaluate function
|
||||
A function that can be called to evaluate a lazily evaluated attribute
|
||||
of an object, such as the value of type aliases created with the :keyword:`type`
|
||||
statement.
|
||||
|
||||
expression
|
||||
A piece of syntax which can be evaluated to some value. In other words,
|
||||
an expression is an accumulation of expression elements like literals,
|
||||
|
|
|
@ -34,11 +34,16 @@ Accessing The Annotations Dict Of An Object In Python 3.10 And Newer
|
|||
|
||||
Python 3.10 adds a new function to the standard library:
|
||||
:func:`inspect.get_annotations`. In Python versions 3.10
|
||||
and newer, calling this function is the best practice for
|
||||
through 3.13, calling this function is the best practice for
|
||||
accessing the annotations dict of any object that supports
|
||||
annotations. This function can also "un-stringize"
|
||||
stringized annotations for you.
|
||||
|
||||
In Python 3.14, there is a new :mod:`annotationlib` module
|
||||
with functionality for working with annotations. This
|
||||
includes a :func:`annotationlib.get_annotations` function,
|
||||
which supersedes :func:`inspect.get_annotations`.
|
||||
|
||||
If for some reason :func:`inspect.get_annotations` isn't
|
||||
viable for your use case, you may access the
|
||||
``__annotations__`` data member manually. Best practice
|
||||
|
@ -184,7 +189,11 @@ Best Practices For ``__annotations__`` In Any Python Version
|
|||
* If you do assign directly to the ``__annotations__`` member
|
||||
of an object, you should always set it to a ``dict`` object.
|
||||
|
||||
* If you directly access the ``__annotations__`` member
|
||||
* You should avoid accessing ``__annotations__`` directly on any object.
|
||||
Instead, use :func:`annotationlib.get_annotations` (Python 3.14+)
|
||||
or :func:`inspect.get_annotations` (Python 3.10+).
|
||||
|
||||
* If you do directly access the ``__annotations__`` member
|
||||
of an object, you should ensure that it's a
|
||||
dictionary before attempting to examine its contents.
|
||||
|
||||
|
@ -231,3 +240,11 @@ itself be quoted. In effect the annotation is quoted
|
|||
|
||||
This prints ``{'a': "'str'"}``. This shouldn't really be considered
|
||||
a "quirk"; it's mentioned here simply because it might be surprising.
|
||||
|
||||
If you use a class with a custom metaclass and access ``__annotations__``
|
||||
on the class, you may observe unexpected behavior; see
|
||||
:pep:`749 <749#pep749-metaclasses>` for some examples. You can avoid these
|
||||
quirks by using :func:`annotationlib.get_annotations` on Python 3.14+ or
|
||||
:func:`inspect.get_annotations` on Python 3.10+. On earlier versions of
|
||||
Python, you can avoid these bugs by accessing the annotations from the
|
||||
class's ``__dict__`` (e.g., ``cls.__dict__.get('__annotations__', None)``).
|
||||
|
|
|
@ -64,8 +64,10 @@ language using this mechanism:
|
|||
| generator_stop | 3.5.0b1 | 3.7 | :pep:`479`: |
|
||||
| | | | *StopIteration handling inside generators* |
|
||||
+------------------+-------------+--------------+---------------------------------------------+
|
||||
| annotations | 3.7.0b1 | TBD [1]_ | :pep:`563`: |
|
||||
| | | | *Postponed evaluation of annotations* |
|
||||
| annotations | 3.7.0b1 | Never [1]_ | :pep:`563`: |
|
||||
| | | | *Postponed evaluation of annotations*, |
|
||||
| | | | :pep:`649`: *Deferred evalutation of |
|
||||
| | | | annotations using descriptors* |
|
||||
+------------------+-------------+--------------+---------------------------------------------+
|
||||
|
||||
.. XXX Adding a new entry? Remember to update simple_stmts.rst, too.
|
||||
|
@ -115,11 +117,9 @@ language using this mechanism:
|
|||
|
||||
.. [1]
|
||||
``from __future__ import annotations`` was previously scheduled to
|
||||
become mandatory in Python 3.10, but the Python Steering Council
|
||||
twice decided to delay the change
|
||||
(`announcement for Python 3.10 <https://mail.python.org/archives/list/python-dev@python.org/message/CLVXXPQ2T2LQ5MP2Y53VVQFCXYWQJHKZ/>`__;
|
||||
`announcement for Python 3.11 <https://mail.python.org/archives/list/python-dev@python.org/message/VIZEBX5EYMSYIJNDBF6DMUMZOCWHARSO/>`__).
|
||||
No final decision has been made yet. See also :pep:`563` and :pep:`649`.
|
||||
become mandatory in Python 3.10, but the change was delayed and ultimately
|
||||
canceled. This feature will eventually be deprecated and removed. See
|
||||
:pep:`649` and :pep:`749`.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
:mod:`!annotationlib` --- Functionality for introspecting annotations
|
||||
=====================================================================
|
||||
|
||||
.. module:: annotationlib
|
||||
:synopsis: Functionality for introspecting annotations
|
||||
|
||||
|
||||
**Source code:** :source:`Lib/annotationlib.py`
|
||||
|
||||
.. testsetup:: default
|
||||
|
||||
import annotationlib
|
||||
from annotationlib import *
|
||||
|
||||
--------------
|
||||
|
||||
The :mod:`!annotationlib` module provides tools for introspecting
|
||||
:term:`annotations <annotation>` on modules, classes, and functions.
|
||||
|
||||
Annotations are :ref:`lazily evaluated <lazy-evaluation>` and often contain
|
||||
forward references to objects that are not yet defined when the annotation
|
||||
is created. This module provides a set of low-level tools that can be used to retrieve annotations in a reliable way, even
|
||||
in the presence of forward references and other edge cases.
|
||||
|
||||
This module supports retrieving annotations in three main formats
|
||||
(see :class:`Format`), each of which works best for different use cases:
|
||||
|
||||
* :attr:`~Format.VALUE` evaluates the annotations and returns their value.
|
||||
This is most straightforward to work with, but it may raise errors,
|
||||
for example if the annotations contain references to undefined names.
|
||||
* :attr:`~Format.FORWARDREF` returns :class:`ForwardRef` objects
|
||||
for annotations that cannot be resolved, allowing you to inspect the
|
||||
annotations without evaluating them. This is useful when you need to
|
||||
work with annotations that may contain unresolved forward references.
|
||||
* :attr:`~Format.SOURCE` returns the annotations as a string, similar
|
||||
to how it would appear in the source file. This is useful for documentation
|
||||
generators that want to display annotations in a readable way.
|
||||
|
||||
The :func:`get_annotations` function is the main entry point for
|
||||
retrieving annotations. Given a function, class, or module, it returns
|
||||
an annotations dictionary in the requested format. This module also provides
|
||||
functionality for working directly with the :term:`annotate function`
|
||||
that is used to evaluate annotations, such as :func:`get_annotate_function`
|
||||
and :func:`call_annotate_function`, as well as the
|
||||
:func:`call_evaluate_function` function for working with
|
||||
:term:`evaluate functions <evaluate function>`.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
:pep:`649` proposed the current model for how annotations work in Python.
|
||||
|
||||
:pep:`749` expanded on various aspects of :pep:`649` and introduced the
|
||||
:mod:`!annotationlib` module.
|
||||
|
||||
:ref:`annotations-howto` provides best practices for working with
|
||||
annotations.
|
||||
|
||||
:pypi:`typing-extensions` provides a backport of :func:`get_annotations`
|
||||
that works on earlier versions of Python.
|
||||
|
||||
Annotation semantics
|
||||
--------------------
|
||||
|
||||
The way annotations are evaluated has changed over the history of Python 3,
|
||||
and currently still depends on a :ref:`future import <future>`.
|
||||
There have been execution models for annotations:
|
||||
|
||||
* *Stock semantics* (default in Python 3.0 through 3.13; see :pep:`3107`
|
||||
and :pep:`526`): Annotations are evaluated eagerly, as they are
|
||||
encountered in the source code.
|
||||
* *Stringified annotations* (used with ``from __future__ import annotations``
|
||||
in Python 3.7 and newer; see :pep:`563`): Annotations are stored as
|
||||
strings only.
|
||||
* *Deferred evaluation* (default in Python 3.14 and newer; see :pep:`649` and
|
||||
:pep:`749`): Annotations are evaluated lazily, only when they are accessed.
|
||||
|
||||
As an example, consider the following program::
|
||||
|
||||
def func(a: Cls) -> None:
|
||||
print(a)
|
||||
|
||||
class Cls: pass
|
||||
|
||||
print(func.__annotations__)
|
||||
|
||||
This will behave as follows:
|
||||
|
||||
* Under stock semantics (Python 3.13 and earlier), it will throw a
|
||||
:exc:`NameError` at the line where ``func`` is defined,
|
||||
because ``Cls`` is an undefined name at that point.
|
||||
* Under stringified annotations (if ``from __future__ import annotations``
|
||||
is used), it will print ``{'a': 'Cls', 'return': 'None'}``.
|
||||
* Under deferred evaluation (Python 3.14 and later), it will print
|
||||
``{'a': <class 'Cls'>, 'return': None}``.
|
||||
|
||||
Stock semantics were used when function annotations were first introduced
|
||||
in Python 3.0 (by :pep:`3107`) because this was the simplest, most obvious
|
||||
way to implement annotations. The same execution model was used when variable
|
||||
annotations were introduced in Python 3.6 (by :pep:`526`). However,
|
||||
stock semantics caused problems when using annotations as type hints,
|
||||
such as a need to refer to names that are not yet defined when the
|
||||
annotation is encountered. In addition, there were performance problems
|
||||
with executing annotations at module import time. Therefore, in Python 3.7,
|
||||
:pep:`563` introduced the ability to store annotations as strings using the
|
||||
``from __future__ import annotations`` syntax. The plan at the time was to
|
||||
eventually make this behavior the default, but a problem appeared:
|
||||
stringified annotations are more difficult to process for those who
|
||||
introspect annotations at runtime. An alternative proposal, :pep:`649`,
|
||||
introduced the third execution model, deferred evaluation, and was implemented
|
||||
in Python 3.14. Stringified annotations are still used if
|
||||
``from __future__ import annotations`` is present, but this behavior will
|
||||
eventually be removed.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: Format
|
||||
|
||||
An :class:`~enum.IntEnum` describing the formats in which annotations
|
||||
can be returned. Members of the enum, or their equivalent integer values,
|
||||
can be passed to :func:`get_annotations` and other functions in this
|
||||
module, as well as to :attr:`~object.__annotate__` functions.
|
||||
|
||||
.. attribute:: VALUE
|
||||
:value: 1
|
||||
|
||||
Values are the result of evaluating the annotation expressions.
|
||||
|
||||
.. attribute:: FORWARDREF
|
||||
:value: 2
|
||||
|
||||
Values are real annotation values (as per :attr:`Format.VALUE` format)
|
||||
for defined values, and :class:`ForwardRef` proxies for undefined
|
||||
values. Real objects may contain references to, :class:`ForwardRef`
|
||||
proxy objects.
|
||||
|
||||
.. attribute:: SOURCE
|
||||
:value: 3
|
||||
|
||||
Values are the text string of the annotation as it appears in the
|
||||
source code, up to modifications including, but not restricted to,
|
||||
whitespace normalizations and constant values optimizations.
|
||||
|
||||
The exact values of these strings may change in future versions of Python.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. class:: ForwardRef
|
||||
|
||||
A proxy object for forward references in annotations.
|
||||
|
||||
Instances of this class are returned when the :attr:`~Format.FORWARDREF`
|
||||
format is used and annotations contain a name that cannot be resolved.
|
||||
This can happen when a forward reference is used in an annotation, such as
|
||||
when a class is referenced before it is defined.
|
||||
|
||||
.. attribute:: __forward_arg__
|
||||
|
||||
A string containing the code that was evaluated to produce the
|
||||
:class:`~ForwardRef`. The string may not be exactly equivalent
|
||||
to the original source.
|
||||
|
||||
.. method:: evaluate(*, globals=None, locals=None, type_params=None, owner=None)
|
||||
|
||||
Evaluate the forward reference, returning its value.
|
||||
|
||||
This may throw an exception, such as :exc:`NameError`, if the forward
|
||||
reference refers to names that do not exist. The arguments to this
|
||||
method can be used to provide bindings for names that would otherwise
|
||||
be undefined.
|
||||
|
||||
:class:`~ForwardRef` instances returned by :func:`get_annotations`
|
||||
retain references to information about the scope they originated from,
|
||||
so calling this method with no further arguments may be sufficient to
|
||||
evaluate such objects. :class:`~ForwardRef` instances created by other
|
||||
means may not have any information about their scope, so passing
|
||||
arguments to this method may be necessary to evaluate them successfully.
|
||||
|
||||
*globals* and *locals* are passed to :func:`eval`, representing
|
||||
the global and local namespaces in which the name is evaluated.
|
||||
*type_params*, if given, must be a tuple of
|
||||
:ref:`type parameters <type-params>` that are in scope while the forward
|
||||
reference is being evaluated. *owner* is the object that owns the
|
||||
annotation from which the forward reference derives, usually a function,
|
||||
class, or module.
|
||||
|
||||
.. important::
|
||||
|
||||
Once a :class:`~ForwardRef` instance has been evaluated, it caches
|
||||
the evaluated value, and future calls to :meth:`evaluate` will return
|
||||
the cached value, regardless of the parameters passed in.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: call_annotate_function(annotate, format, *, owner=None)
|
||||
|
||||
Call the :term:`annotate function` *annotate* with the given *format*,
|
||||
a member of the :class:`Format` enum, and return the annotations
|
||||
dictionary produced by the function.
|
||||
|
||||
This helper function is required because annotate functions generated by
|
||||
the compiler for functions, classes, and modules only support
|
||||
the :attr:`~Format.VALUE` format when called directly.
|
||||
To support other formats, this function calls the annotate function
|
||||
in a special environment that allows it to produce annotations in the
|
||||
other formats. This is a useful building block when implementing
|
||||
functionality that needs to partially evaluate annotations while a class
|
||||
is being constructed.
|
||||
|
||||
*owner* is the object that owns the annotation function, usually
|
||||
a function, class, or module. If provided, it is used in the
|
||||
:attr:`~Format.FORWARDREF` format to produce a :class:`ForwardRef`
|
||||
object that carries more information.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:PEP:`PEP 649 <649#the-stringizer-and-the-fake-globals-environment>`
|
||||
contains an explanation of the implementation technique used by this
|
||||
function.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. function:: call_evaluate_function(evaluate, format, *, owner=None)
|
||||
|
||||
Call the :term:`evaluate function` *evaluate* with the given *format*,
|
||||
a member of the :class:`Format` enum, and return the value produced by
|
||||
the function. This is similar to :func:`call_annotate_function`,
|
||||
but the latter always returns a dictionary mapping strings to annotations,
|
||||
while this function returns a single value.
|
||||
|
||||
This is intended for use with the evaluate functions generated for lazily
|
||||
evaluated elements related to type aliases and type parameters:
|
||||
|
||||
* :meth:`typing.TypeAliasType.evaluate_value`, the value of type aliases
|
||||
* :meth:`typing.TypeVar.evaluate_bound`, the bound of type variables
|
||||
* :meth:`typing.TypeVar.evaluate_constraints`, the constraints of
|
||||
type variables
|
||||
* :meth:`typing.TypeVar.evaluate_default`, the default value of
|
||||
type variables
|
||||
* :meth:`typing.ParamSpec.evaluate_default`, the default value of
|
||||
parameter specifications
|
||||
* :meth:`typing.TypeVarTuple.evaluate_default`, the default value of
|
||||
type variable tuples
|
||||
|
||||
*owner* is the object that owns the evaluate function, such as the type
|
||||
alias or type variable object.
|
||||
|
||||
*format* can be used to control the format in which the value is returned:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> type Alias = undefined
|
||||
>>> call_evaluate_function(Alias.evaluate_value, Format.VALUE)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
NameError: name 'undefined' is not defined
|
||||
>>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)
|
||||
ForwardRef('undefined')
|
||||
>>> call_evaluate_function(Alias.evaluate_value, Format.SOURCE)
|
||||
'undefined'
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. function:: get_annotate_function(obj)
|
||||
|
||||
Retrieve the :term:`annotate function` for *obj*. Return :const:`!None`
|
||||
if *obj* does not have an annotate function.
|
||||
|
||||
This is usually equivalent to accessing the :attr:`~object.__annotate__`
|
||||
attribute of *obj*, but direct access to the attribute may return the wrong
|
||||
object in certain situations involving metaclasses. This function should be
|
||||
used instead of accessing the attribute directly.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. function:: get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=Format.VALUE)
|
||||
|
||||
Compute the annotations dict for an object.
|
||||
|
||||
*obj* may be a callable, class, module, or other object with
|
||||
:attr:`~object.__annotate__` and :attr:`~object.__annotations__` attributes.
|
||||
Passing in an object of any other type raises :exc:`TypeError`.
|
||||
|
||||
The *format* parameter controls the format in which annotations are returned,
|
||||
and must be a member of the :class:`Format` enum or its integer equivalent.
|
||||
|
||||
Returns a dict. :func:`!get_annotations` returns a new dict every time
|
||||
it's called; calling it twice on the same object will return two
|
||||
different but equivalent dicts.
|
||||
|
||||
This function handles several details for you:
|
||||
|
||||
* If *eval_str* is true, values of type :class:`!str` will
|
||||
be un-stringized using :func:`eval`. This is intended
|
||||
for use with stringized annotations
|
||||
(``from __future__ import annotations``). It is an error
|
||||
to set *eval_str* to true with formats other than :attr:`Format.VALUE`.
|
||||
* If *obj* doesn't have an annotations dict, returns an
|
||||
empty dict. (Functions and methods always have an
|
||||
annotations dict; classes, modules, and other types of
|
||||
callables may not.)
|
||||
* Ignores inherited annotations on classes, as well as annotations
|
||||
on metaclasses. If a class
|
||||
doesn't have its own annotations dict, returns an empty dict.
|
||||
* All accesses to object members and dict values are done
|
||||
using ``getattr()`` and ``dict.get()`` for safety.
|
||||
|
||||
*eval_str* controls whether or not values of type :class:`!str` are
|
||||
replaced with the result of calling :func:`eval` on those values:
|
||||
|
||||
* If eval_str is true, :func:`eval` is called on values of type
|
||||
:class:`!str`. (Note that :func:`!get_annotations` doesn't catch
|
||||
exceptions; if :func:`eval()` raises an exception, it will unwind
|
||||
the stack past the :func:`!get_annotations` call.)
|
||||
* If *eval_str* is false (the default), values of type :class:`!str` are
|
||||
unchanged.
|
||||
|
||||
*globals* and *locals* are passed in to :func:`eval`; see the documentation
|
||||
for :func:`eval` for more information. If *globals* or *locals*
|
||||
is :const:`!None`, this function may replace that value with a
|
||||
context-specific default, contingent on ``type(obj)``:
|
||||
|
||||
* If *obj* is a module, *globals* defaults to ``obj.__dict__``.
|
||||
* If *obj* is a class, *globals* defaults to
|
||||
``sys.modules[obj.__module__].__dict__`` and *locals* defaults
|
||||
to the *obj* class namespace.
|
||||
* If *obj* is a callable, *globals* defaults to
|
||||
:attr:`obj.__globals__ <function.__globals__>`,
|
||||
although if *obj* is a wrapped function (using
|
||||
:func:`functools.update_wrapper`) or a :class:`functools.partial` object,
|
||||
it is unwrapped until a non-wrapped function is found.
|
||||
|
||||
Calling :func:`!get_annotations` is best practice for accessing the
|
||||
annotations dict of any object. See :ref:`annotations-howto` for
|
||||
more information on annotations best practices.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> def f(a: int, b: str) -> float:
|
||||
... pass
|
||||
>>> get_annotations(f)
|
||||
{'a': <class 'int'>, 'b': <class 'str'>, 'return': <class 'float'>}
|
||||
|
||||
.. versionadded:: 3.14
|
|
@ -718,19 +718,19 @@ function.
|
|||
Accepts a wide range of Python callables, from plain functions and classes to
|
||||
:func:`functools.partial` objects.
|
||||
|
||||
For objects defined in modules using stringized annotations
|
||||
(``from __future__ import annotations``), :func:`signature` will
|
||||
If some of the annotations are strings (e.g., because
|
||||
``from __future__ import annotations`` was used), :func:`signature` will
|
||||
attempt to automatically un-stringize the annotations using
|
||||
:func:`get_annotations`. The
|
||||
:func:`annotationlib.get_annotations`. The
|
||||
*globals*, *locals*, and *eval_str* parameters are passed
|
||||
into :func:`get_annotations` when resolving the
|
||||
annotations; see the documentation for :func:`get_annotations`
|
||||
into :func:`!annotationlib.get_annotations` when resolving the
|
||||
annotations; see the documentation for :func:`!annotationlib.get_annotations`
|
||||
for instructions on how to use these parameters.
|
||||
|
||||
Raises :exc:`ValueError` if no signature can be provided, and
|
||||
:exc:`TypeError` if that type of object is not supported. Also,
|
||||
if the annotations are stringized, and *eval_str* is not false,
|
||||
the ``eval()`` call(s) to un-stringize the annotations in :func:`get_annotations`
|
||||
the ``eval()`` call(s) to un-stringize the annotations in :func:`annotationlib.get_annotations`
|
||||
could potentially raise any kind of exception.
|
||||
|
||||
A slash(/) in the signature of a function denotes that the parameters prior
|
||||
|
@ -1247,62 +1247,19 @@ Classes and functions
|
|||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. function:: get_annotations(obj, *, globals=None, locals=None, eval_str=False)
|
||||
.. function:: get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=annotationlib.Format.VALUE)
|
||||
|
||||
Compute the annotations dict for an object.
|
||||
|
||||
``obj`` may be a callable, class, or module.
|
||||
Passing in an object of any other type raises :exc:`TypeError`.
|
||||
|
||||
Returns a dict. ``get_annotations()`` returns a new dict every time
|
||||
it's called; calling it twice on the same object will return two
|
||||
different but equivalent dicts.
|
||||
|
||||
This function handles several details for you:
|
||||
|
||||
* If ``eval_str`` is true, values of type ``str`` will
|
||||
be un-stringized using :func:`eval`. This is intended
|
||||
for use with stringized annotations
|
||||
(``from __future__ import annotations``).
|
||||
* If ``obj`` doesn't have an annotations dict, returns an
|
||||
empty dict. (Functions and methods always have an
|
||||
annotations dict; classes, modules, and other types of
|
||||
callables may not.)
|
||||
* Ignores inherited annotations on classes. If a class
|
||||
doesn't have its own annotations dict, returns an empty dict.
|
||||
* All accesses to object members and dict values are done
|
||||
using ``getattr()`` and ``dict.get()`` for safety.
|
||||
* Always, always, always returns a freshly created dict.
|
||||
|
||||
``eval_str`` controls whether or not values of type ``str`` are replaced
|
||||
with the result of calling :func:`eval` on those values:
|
||||
|
||||
* If eval_str is true, :func:`eval` is called on values of type ``str``.
|
||||
(Note that ``get_annotations`` doesn't catch exceptions; if :func:`eval`
|
||||
raises an exception, it will unwind the stack past the ``get_annotations``
|
||||
call.)
|
||||
* If eval_str is false (the default), values of type ``str`` are unchanged.
|
||||
|
||||
``globals`` and ``locals`` are passed in to :func:`eval`; see the documentation
|
||||
for :func:`eval` for more information. If ``globals`` or ``locals``
|
||||
is ``None``, this function may replace that value with a context-specific
|
||||
default, contingent on ``type(obj)``:
|
||||
|
||||
* If ``obj`` is a module, ``globals`` defaults to ``obj.__dict__``.
|
||||
* If ``obj`` is a class, ``globals`` defaults to
|
||||
``sys.modules[obj.__module__].__dict__`` and ``locals`` defaults
|
||||
to the ``obj`` class namespace.
|
||||
* If ``obj`` is a callable, ``globals`` defaults to
|
||||
:attr:`obj.__globals__ <function.__globals__>`,
|
||||
although if ``obj`` is a wrapped function (using
|
||||
:func:`functools.update_wrapper`) it is first unwrapped.
|
||||
|
||||
Calling ``get_annotations`` is best practice for accessing the
|
||||
annotations dict of any object. See :ref:`annotations-howto` for
|
||||
more information on annotations best practices.
|
||||
This is an alias for :func:`annotationlib.get_annotations`; see the documentation
|
||||
of that function for more information.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
This function is now an alias for :func:`annotationlib.get_annotations`.
|
||||
Calling it as ``inspect.get_annotations`` will continue to work.
|
||||
|
||||
|
||||
.. _inspect-stack:
|
||||
|
||||
|
|
|
@ -25,4 +25,5 @@ overview:
|
|||
__future__.rst
|
||||
gc.rst
|
||||
inspect.rst
|
||||
annotationlib.rst
|
||||
site.rst
|
||||
|
|
|
@ -1825,6 +1825,16 @@ without the dedicated syntax, as documented below.
|
|||
the bound is evaluated only when the attribute is accessed, not when
|
||||
the type variable is created (see :ref:`lazy-evaluation`).
|
||||
|
||||
.. method:: evaluate_bound
|
||||
|
||||
An :term:`evaluate function` corresponding to the :attr:`~TypeVar.__bound__` attribute.
|
||||
When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
|
||||
format, which is equivalent to accessing the :attr:`~TypeVar.__bound__` attribute directly,
|
||||
but the method object can be passed to :func:`annotationlib.call_evaluate_function`
|
||||
to evaluate the value in a different format.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. attribute:: __constraints__
|
||||
|
||||
A tuple containing the constraints of the type variable, if any.
|
||||
|
@ -1835,6 +1845,16 @@ without the dedicated syntax, as documented below.
|
|||
the constraints are evaluated only when the attribute is accessed, not when
|
||||
the type variable is created (see :ref:`lazy-evaluation`).
|
||||
|
||||
.. method:: evaluate_constraints
|
||||
|
||||
An :term:`evaluate function` corresponding to the :attr:`~TypeVar.__constraints__` attribute.
|
||||
When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
|
||||
format, which is equivalent to accessing the :attr:`~TypeVar.__constraints__` attribute directly,
|
||||
but the method object can be passed to :func:`annotationlib.call_evaluate_function`
|
||||
to evaluate the value in a different format.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. attribute:: __default__
|
||||
|
||||
The default value of the type variable, or :data:`typing.NoDefault` if it
|
||||
|
@ -1842,6 +1862,16 @@ without the dedicated syntax, as documented below.
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. method:: evaluate_default
|
||||
|
||||
An :term:`evaluate function` corresponding to the :attr:`~TypeVar.__default__` attribute.
|
||||
When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
|
||||
format, which is equivalent to accessing the :attr:`~TypeVar.__default__` attribute directly,
|
||||
but the method object can be passed to :func:`annotationlib.call_evaluate_function`
|
||||
to evaluate the value in a different format.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. method:: has_default()
|
||||
|
||||
Return whether or not the type variable has a default value. This is equivalent
|
||||
|
@ -1980,6 +2010,16 @@ without the dedicated syntax, as documented below.
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. method:: evaluate_default
|
||||
|
||||
An :term:`evaluate function` corresponding to the :attr:`~TypeVarTuple.__default__` attribute.
|
||||
When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
|
||||
format, which is equivalent to accessing the :attr:`~TypeVarTuple.__default__` attribute directly,
|
||||
but the method object can be passed to :func:`annotationlib.call_evaluate_function`
|
||||
to evaluate the value in a different format.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. method:: has_default()
|
||||
|
||||
Return whether or not the type variable tuple has a default value. This is equivalent
|
||||
|
@ -2076,6 +2116,16 @@ without the dedicated syntax, as documented below.
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. method:: evaluate_default
|
||||
|
||||
An :term:`evaluate function` corresponding to the :attr:`~ParamSpec.__default__` attribute.
|
||||
When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
|
||||
format, which is equivalent to accessing the :attr:`~ParamSpec.__default__` attribute directly,
|
||||
but the method object can be passed to :func:`annotationlib.call_evaluate_function`
|
||||
to evaluate the value in a different format.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. method:: has_default()
|
||||
|
||||
Return whether or not the parameter specification has a default value. This is equivalent
|
||||
|
@ -2200,6 +2250,32 @@ without the dedicated syntax, as documented below.
|
|||
>>> Recursive.__value__
|
||||
Mutually
|
||||
|
||||
.. method:: evaluate_value
|
||||
|
||||
An :term:`evaluate function` corresponding to the :attr:`__value__` attribute.
|
||||
When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
|
||||
format, which is equivalent to accessing the :attr:`__value__` attribute directly,
|
||||
but the method object can be passed to :func:`annotationlib.call_evaluate_function`
|
||||
to evaluate the value in a different format:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> type Alias = undefined
|
||||
>>> Alias.__value__
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
NameError: name 'undefined' is not defined
|
||||
>>> from annotationlib import Format, call_evaluate_function
|
||||
>>> Alias.evaluate_value(Format.VALUE)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
NameError: name 'undefined' is not defined
|
||||
>>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)
|
||||
ForwardRef('undefined')
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
|
||||
Other special directives
|
||||
""""""""""""""""""""""""
|
||||
|
||||
|
@ -3306,7 +3382,7 @@ Introspection helpers
|
|||
Class used for internal typing representation of string forward references.
|
||||
|
||||
For example, ``List["SomeClass"]`` is implicitly transformed into
|
||||
``List[ForwardRef("SomeClass")]``. ``ForwardRef`` should not be instantiated by
|
||||
``List[ForwardRef("SomeClass")]``. :class:`!ForwardRef` should not be instantiated by
|
||||
a user, but may be used by introspection tools.
|
||||
|
||||
.. note::
|
||||
|
@ -3316,6 +3392,39 @@ Introspection helpers
|
|||
|
||||
.. versionadded:: 3.7.4
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
This is now an alias for :class:`annotationlib.ForwardRef`.
|
||||
|
||||
.. function:: evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=annotationlib.Format.VALUE)
|
||||
|
||||
Evaluate an :class:`annotationlib.ForwardRef` as a :term:`type hint`.
|
||||
|
||||
This is similar to calling :meth:`annotationlib.ForwardRef.evaluate`,
|
||||
but unlike that method, :func:`!evaluate_forward_ref` also:
|
||||
|
||||
* Recursively evaluates forward references nested within the type hint.
|
||||
* Raises :exc:`TypeError` when it encounters certain objects that are
|
||||
not valid type hints.
|
||||
* Replaces type hints that evaluate to :const:`!None` with
|
||||
:class:`types.NoneType`.
|
||||
* Supports the :attr:`~annotationlib.Format.FORWARDREF` and
|
||||
:attr:`~annotationlib.Format.SOURCE` formats.
|
||||
|
||||
*forward_ref* must be an instance of :class:`~annotationlib.ForwardRef`.
|
||||
*owner*, if given, should be the object that holds the annotations that
|
||||
the forward reference derived from, such as a module, class object, or function.
|
||||
It is used to infer the namespaces to use for looking up names.
|
||||
*globals* and *locals* can also be explicitly given to provide
|
||||
the global and local namespaces.
|
||||
*type_params* is a tuple of :ref:`type parameters <type-params>` that
|
||||
are in scope when evaluating the forward reference.
|
||||
This parameter must be provided (though it may be an empty tuple) if *owner*
|
||||
is not given and the forward reference does not already have an owner set.
|
||||
*format* specifies the format of the annotation and is a member of
|
||||
the :class:`annotationlib.Format` enum.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. data:: NoDefault
|
||||
|
||||
A sentinel object used to indicate that a type parameter has no default
|
||||
|
|
|
@ -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…
Reference in New Issue