mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
[3.12] gh-103921: Document PEP 695 (GH-104642) (#104989)
(cherry picked from commit 060277d96b
)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
bb1e57ee40
commit
dcee0aa911
11 changed files with 1240 additions and 308 deletions
|
@ -443,45 +443,38 @@ static PyMethodDef typevar_methods[] = {
|
|||
PyDoc_STRVAR(typevar_doc,
|
||||
"Type variable.\n\
|
||||
\n\
|
||||
Usage::\n\
|
||||
The preferred way to construct a type variable is via the dedicated syntax\n\
|
||||
for generic functions, classes, and type aliases:\n\
|
||||
\n\
|
||||
T = TypeVar('T') # Can be anything\n\
|
||||
A = TypeVar('A', str, bytes) # Must be str or bytes\n\
|
||||
class Sequence[T]: # T is a TypeVar\n\
|
||||
...\n\
|
||||
\n\
|
||||
This syntax can also be used to create bound and constrained type\n\
|
||||
variables:\n\
|
||||
\n\
|
||||
class StrSequence[S: str]: # S is a TypeVar bound to str\n\
|
||||
...\n\
|
||||
\n\
|
||||
class StrOrBytesSequence[A: (str, bytes)]: # A is a TypeVar constrained to str or bytes\n\
|
||||
...\n\
|
||||
\n\
|
||||
However, if desired, reusable type variables can also be constructed\n\
|
||||
manually, like so:\n\
|
||||
\n\
|
||||
T = TypeVar('T') # Can be anything\n\
|
||||
S = TypeVar('S', bound=str) # Can be any subtype of str\n\
|
||||
A = TypeVar('A', str, bytes) # Must be exactly str or bytes\n\
|
||||
\n\
|
||||
Type variables exist primarily for the benefit of static type\n\
|
||||
checkers. They serve as the parameters for generic types as well\n\
|
||||
as for generic function definitions. See class Generic for more\n\
|
||||
information on generic types. Generic functions work as follows:\n\
|
||||
as for generic function and type alias definitions.\n\
|
||||
\n\
|
||||
def repeat(x: T, n: int) -> List[T]:\n\
|
||||
'''Return a list containing n references to x.'''\n\
|
||||
return [x]*n\n\
|
||||
\n\
|
||||
def longest(x: A, y: A) -> A:\n\
|
||||
'''Return the longest of two strings.'''\n\
|
||||
return x if len(x) >= len(y) else y\n\
|
||||
\n\
|
||||
The latter example's signature is essentially the overloading\n\
|
||||
of (str, str) -> str and (bytes, bytes) -> bytes. Also note\n\
|
||||
that if the arguments are instances of some subclass of str,\n\
|
||||
the return type is still plain str.\n\
|
||||
\n\
|
||||
At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError.\n\
|
||||
\n\
|
||||
Type variables defined with covariant=True or contravariant=True\n\
|
||||
can be used to declare covariant or contravariant generic types.\n\
|
||||
See PEP 484 for more details. By default generic types are invariant\n\
|
||||
in all type variables.\n\
|
||||
\n\
|
||||
Type variables can be introspected. e.g.:\n\
|
||||
\n\
|
||||
T.__name__ == 'T'\n\
|
||||
T.__constraints__ == ()\n\
|
||||
T.__covariant__ == False\n\
|
||||
T.__contravariant__ = False\n\
|
||||
A.__constraints__ == (str, bytes)\n\
|
||||
\n\
|
||||
Note that only type variables defined in global scope can be pickled.\n\
|
||||
The variance of type variables is inferred by type checkers when they are created\n\
|
||||
through the type parameter syntax and when ``infer_variance=True`` is passed.\n\
|
||||
Manually created type variables may be explicitly marked covariant or\n\
|
||||
contravariant by passing ``covariant=True`` or ``contravariant=True``.\n\
|
||||
By default, manually created type variables are invariant. See PEP 484\n\
|
||||
and PEP 695 for more details.\n\
|
||||
");
|
||||
|
||||
static PyType_Slot typevar_slots[] = {
|
||||
|
@ -942,7 +935,14 @@ static PyMethodDef paramspec_methods[] = {
|
|||
PyDoc_STRVAR(paramspec_doc,
|
||||
"Parameter specification variable.\n\
|
||||
\n\
|
||||
Usage::\n\
|
||||
The preferred way to construct a parameter specification is via the dedicated syntax\n\
|
||||
for generic functions, classes, and type aliases, where\n\
|
||||
the use of '**' creates a parameter specification:\n\
|
||||
\n\
|
||||
type IntFunc[**P] = Callable[P, int]\n\
|
||||
\n\
|
||||
For compatibility with Python 3.11 and earlier, ParamSpec objects\n\
|
||||
can also be created as follows:\n\
|
||||
\n\
|
||||
P = ParamSpec('P')\n\
|
||||
\n\
|
||||
|
@ -952,12 +952,9 @@ callable to another callable, a pattern commonly found in higher order\n\
|
|||
functions and decorators. They are only valid when used in ``Concatenate``,\n\
|
||||
or as the first argument to ``Callable``, or as parameters for user-defined\n\
|
||||
Generics. See class Generic for more information on generic types. An\n\
|
||||
example for annotating a decorator::\n\
|
||||
example for annotating a decorator:\n\
|
||||
\n\
|
||||
T = TypeVar('T')\n\
|
||||
P = ParamSpec('P')\n\
|
||||
\n\
|
||||
def add_logging(f: Callable[P, T]) -> Callable[P, T]:\n\
|
||||
def add_logging[**P, T](f: Callable[P, T]) -> Callable[P, T]:\n\
|
||||
'''A type-safe decorator to add logging to a function.'''\n\
|
||||
def inner(*args: P.args, **kwargs: P.kwargs) -> T:\n\
|
||||
logging.info(f'{f.__name__} was called')\n\
|
||||
|
@ -969,17 +966,9 @@ example for annotating a decorator::\n\
|
|||
'''Add two numbers together.'''\n\
|
||||
return x + y\n\
|
||||
\n\
|
||||
Parameter specification variables defined with covariant=True or\n\
|
||||
contravariant=True can be used to declare covariant or contravariant\n\
|
||||
generic types. These keyword arguments are valid, but their actual semantics\n\
|
||||
are yet to be decided. See PEP 612 for details.\n\
|
||||
\n\
|
||||
Parameter specification variables can be introspected. e.g.:\n\
|
||||
\n\
|
||||
P.__name__ == 'P'\n\
|
||||
P.__bound__ == None\n\
|
||||
P.__covariant__ == False\n\
|
||||
P.__contravariant__ == False\n\
|
||||
\n\
|
||||
Note that only parameter specification variables defined in global scope can\n\
|
||||
be pickled.\n\
|
||||
|
@ -1175,9 +1164,18 @@ static PyMethodDef typevartuple_methods[] = {
|
|||
};
|
||||
|
||||
PyDoc_STRVAR(typevartuple_doc,
|
||||
"Type variable tuple.\n\
|
||||
"Type variable tuple. A specialized form of type variable that enables\n\
|
||||
variadic generics.\n\
|
||||
\n\
|
||||
Usage:\n\
|
||||
The preferred way to construct a type variable tuple is via the dedicated syntax\n\
|
||||
for generic functions, classes, and type aliases, where a single\n\
|
||||
'*' indicates a type variable tuple:\n\
|
||||
\n\
|
||||
def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]:\n\
|
||||
return (*tup[1:], tup[0])\n\
|
||||
\n\
|
||||
For compatibility with Python 3.11 and earlier, TypeVarTuple objects\n\
|
||||
can also be created as follows:\n\
|
||||
\n\
|
||||
Ts = TypeVarTuple('Ts') # Can be given any name\n\
|
||||
\n\
|
||||
|
@ -1185,7 +1183,7 @@ Just as a TypeVar (type variable) is a placeholder for a single type,\n\
|
|||
a TypeVarTuple is a placeholder for an *arbitrary* number of types. For\n\
|
||||
example, if we define a generic class using a TypeVarTuple:\n\
|
||||
\n\
|
||||
class C(Generic[*Ts]): ...\n\
|
||||
class C[*Ts]: ...\n\
|
||||
\n\
|
||||
Then we can parameterize that class with an arbitrary number of type\n\
|
||||
arguments:\n\
|
||||
|
@ -1441,6 +1439,23 @@ PyDoc_STRVAR(typealias_doc,
|
|||
Type aliases are created through the type statement:\n\
|
||||
\n\
|
||||
type Alias = int\n\
|
||||
\n\
|
||||
In this example, Alias and int will be treated equivalently by static\n\
|
||||
type checkers.\n\
|
||||
\n\
|
||||
At runtime, Alias is an instance of TypeAliasType. The __name__ attribute\n\
|
||||
holds the name of the type alias. The value of the type\n\
|
||||
alias is stored in the __value__ attribute. It is evaluated lazily, so\n\
|
||||
the value is computed only if the attribute is accessed.\n\
|
||||
\n\
|
||||
Type aliases can also be generic:\n\
|
||||
\n\
|
||||
type ListOrSet[T] = list[T] | set[T]\n\
|
||||
\n\
|
||||
In this case, the type parameters of the alias are stored in the\n\
|
||||
__type_params__ attribute.\n\
|
||||
\n\
|
||||
See PEP 695 for more information.\n\
|
||||
");
|
||||
|
||||
static PyNumberMethods typealias_as_number = {
|
||||
|
@ -1489,14 +1504,14 @@ PyDoc_STRVAR(generic_doc,
|
|||
\n\
|
||||
A generic type is typically declared by inheriting from\n\
|
||||
this class parameterized with one or more type variables.\n\
|
||||
For example, a generic mapping type might be defined as::\n\
|
||||
For example, a generic mapping type might be defined as:\n\
|
||||
\n\
|
||||
class Mapping(Generic[KT, VT]):\n\
|
||||
def __getitem__(self, key: KT) -> VT:\n\
|
||||
...\n\
|
||||
# Etc.\n\
|
||||
\n\
|
||||
This class can then be used as follows::\n\
|
||||
This class can then be used as follows:\n\
|
||||
\n\
|
||||
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:\n\
|
||||
try:\n\
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue