A type, introduced in PEP 593 (Flexible function and variable
annotations), to decorate existing types with context-specific metadata
(possibly multiple pieces of it, as Annotated is variadic).
Specifically, a type T can be annotated with metadata x via the
typehint Annotated[T, x]. This metadata can be used for either static
analysis or at runtime. If a library (or tool) encounters a typehint
Annotated[T, x] and has no special logic for metadata x, it
should ignore it and simply treat the type as T. Unlike the
no_type_check functionality that currently exists in the typing
module which completely disables typechecking annotations on a function
or a class, the Annotated type allows for both static typechecking
of T (e.g., via mypy or Pyre, which can safely ignore x)
together with runtime access to x within a specific application.
Ultimately, the responsibility of how to interpret the annotations (if
at all) is the responsibility of the tool or library encountering the
Annotated type. A tool or library encountering an Annotated type
can scan through the annotations to determine if they are of interest
(e.g., using isinstance()).
When a tool or a library does not support annotations or encounters an
unknown annotation it should just ignore it and treat annotated type as
the underlying type.
It's up to the tool consuming the annotations to decide whether the
client is allowed to have several annotations on one type and how to
merge those annotations.
Since the Annotated type allows you to put several annotations of
the same (or different) type(s) on any node, the tools or libraries
consuming those annotations are in charge of dealing with potential
duplicates. For example, if you are doing value range analysis you might
allow this:
T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]
Passing include_extras=True to get_type_hints() lets one
access the extra annotations at runtime.
The details of the syntax:
The first argument to Annotated must be a valid type
Multiple type annotations are supported (Annotated supports variadic
arguments):
Annotated[int, ValueRange(3, 10), ctype("char")]
Annotated must be called with at least two arguments (
Annotated[int] is not valid)
The order of the annotations is preserved and matters for equality
checks:
Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[
int, ctype("char"), ValueRange(3, 10)
]
Nested Annotated types are flattened, with metadata ordered
starting with the innermost annotation:
Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
int, ValueRange(3, 10), ctype("char")
]
Duplicated annotations are not removed:
Annotated[int, ValueRange(3, 10)] != Annotated[
int, ValueRange(3, 10), ValueRange(3, 10)
]
Annotated can be used with nested and generic aliases:
T = TypeVar('T')
Vec = Annotated[list[tuple[T, T]], MaxLen(10)]
V = Vec[int]
V == Annotated[list[tuple[int, int]], MaxLen(10)]
3.9 新版功能.