aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Doc/library/typing.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/library/typing.rst')
-rw-r--r--Doc/library/typing.rst87
1 files changed, 61 insertions, 26 deletions
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index 3afcba6e898..69df09c7795 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -1098,6 +1098,12 @@ These can be used as types in annotations. They all support subscription using
Union[Union[int, str], float] == Union[int, str, float]
+ However, this does not apply to unions referenced through a type
+ alias, to avoid forcing evaluation of the underlying :class:`TypeAliasType`::
+
+ type A = Union[int, str]
+ Union[A, float] != Union[int, str, float]
+
* Unions of a single argument vanish, e.g.::
Union[int] == int # The constructor actually returns int
@@ -1230,6 +1236,32 @@ These can be used as types in annotations. They all support subscription using
is allowed as type argument to ``Literal[...]``, but type checkers may
impose restrictions. See :pep:`586` for more details about literal types.
+ Additional details:
+
+ * The arguments must be literal values and there must be at least one.
+
+ * Nested ``Literal`` types are flattened, e.g.::
+
+ assert Literal[Literal[1, 2], 3] == Literal[1, 2, 3]
+
+ However, this does not apply to ``Literal`` types referenced through a type
+ alias, to avoid forcing evaluation of the underlying :class:`TypeAliasType`::
+
+ type A = Literal[1, 2]
+ assert Literal[A, 3] != Literal[1, 2, 3]
+
+ * Redundant arguments are skipped, e.g.::
+
+ assert Literal[1, 2, 1] == Literal[1, 2]
+
+ * When comparing literals, the argument order is ignored, e.g.::
+
+ assert Literal[1, 2] == Literal[2, 1]
+
+ * You cannot subclass or instantiate a ``Literal``.
+
+ * You cannot write ``Literal[X][Y]``.
+
.. versionadded:: 3.8
.. versionchanged:: 3.9.1
@@ -1400,6 +1432,14 @@ These can be used as types in annotations. They all support subscription using
int, ValueRange(3, 10), ctype("char")
]
+ However, this does not apply to ``Annotated`` types referenced through a type
+ alias, to avoid forcing evaluation of the underlying :class:`TypeAliasType`::
+
+ type From3To10[T] = Annotated[T, ValueRange(3, 10)]
+ assert Annotated[From3To10[int], ctype("char")] != Annotated[
+ int, ValueRange(3, 10), ctype("char")
+ ]
+
Duplicated metadata elements are not removed::
assert Annotated[int, ValueRange(3, 10)] != Annotated[
@@ -3460,20 +3500,11 @@ Introspection helpers
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.STRING` formats.
+ but unlike that method, :func:`!evaluate_forward_ref` also
+ recursively evaluates forward references nested within the type hint.
See the documentation for :meth:`annotationlib.ForwardRef.evaluate` for
- the meaning of the *owner*, *globals*, *locals*, and *type_params* parameters.
- *format* specifies the format of the annotation and is a member of
- the :class:`annotationlib.Format` enum.
+ the meaning of the *owner*, *globals*, *locals*, *type_params*, and *format* parameters.
.. versionadded:: 3.14
@@ -3499,28 +3530,32 @@ Constant
.. data:: TYPE_CHECKING
A special constant that is assumed to be ``True`` by 3rd party static
- type checkers. It is ``False`` at runtime.
+ type checkers. It's ``False`` at runtime.
+
+ A module which is expensive to import, and which only contain types
+ used for typing annotations, can be safely imported inside an
+ ``if TYPE_CHECKING:`` block. This prevents the module from actually
+ being imported at runtime; annotations aren't eagerly evaluated
+ (see :pep:`649`) so using undefined symbols in annotations is
+ harmless--as long as you don't later examine them.
+ Your static type analysis tool will set ``TYPE_CHECKING`` to
+ ``True`` during static type analysis, which means the module will
+ be imported and the types will be checked properly during such analysis.
Usage::
if TYPE_CHECKING:
import expensive_mod
- def fun(arg: 'expensive_mod.SomeType') -> None:
+ def fun(arg: expensive_mod.SomeType) -> None:
local_var: expensive_mod.AnotherType = other_fun()
- The first type annotation must be enclosed in quotes, making it a
- "forward reference", to hide the ``expensive_mod`` reference from the
- interpreter runtime. Type annotations for local variables are not
- evaluated, so the second annotation does not need to be enclosed in quotes.
-
- .. note::
-
- If ``from __future__ import annotations`` is used,
- annotations are not evaluated at function definition time.
- Instead, they are stored as strings in ``__annotations__``.
- This makes it unnecessary to use quotes around the annotation
- (see :pep:`563`).
+ If you occasionally need to examine type annotations at runtime
+ which may contain undefined symbols, use
+ :meth:`annotationlib.get_annotations` with a ``format`` parameter
+ of :attr:`annotationlib.Format.STRING` or
+ :attr:`annotationlib.Format.FORWARDREF` to safely retrieve the
+ annotations without raising :exc:`NameError`.
.. versionadded:: 3.5.2