|
18 | 18 | --------------
|
19 | 19 |
|
20 | 20 | This module provides runtime support for type hints as specified by
|
21 |
| -:pep:`484`, :pep:`526`, :pep:`544`, :pep:`586`, :pep:`589`, :pep:`591`, and :pep:`613`. |
| 21 | +:pep:`484`, :pep:`526`, :pep:`544`, :pep:`586`, :pep:`589`, :pep:`591`, |
| 22 | +:pep:`612` and :pep:`613`. |
22 | 23 | The most fundamental support consists of the types :data:`Any`, :data:`Union`,
|
23 | 24 | :data:`Tuple`, :data:`Callable`, :class:`TypeVar`, and
|
24 | 25 | :class:`Generic`. For full specification please see :pep:`484`. For
|
@@ -171,6 +172,22 @@ It is possible to declare the return type of a callable without specifying
|
171 | 172 | the call signature by substituting a literal ellipsis
|
172 | 173 | for the list of arguments in the type hint: ``Callable[..., ReturnType]``.
|
173 | 174 |
|
| 175 | +Callables which take other callables as arguments may indicate that their |
| 176 | +parameter types are dependent on each other using :class:`ParamSpec`. |
| 177 | +Additionally, if that callable adds or removes arguments from other |
| 178 | +callables, the :data:`Concatenate` operator may be used. They |
| 179 | +take the form ``Callable[ParamSpecVariable, ReturnType]`` and |
| 180 | +``Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]`` |
| 181 | +respectively. |
| 182 | + |
| 183 | +.. versionchanged:: 3.10 |
| 184 | + ``Callable`` now supports :class:`ParamSpec` and :data:`Concatenate`. |
| 185 | + See :pep:`612` for more information. |
| 186 | + |
| 187 | +.. seealso:: |
| 188 | + The documentation for :class:`ParamSpec` and :class:`Concatenate` provide |
| 189 | + examples of usage in ``Callable``. |
| 190 | + |
174 | 191 | .. _generics:
|
175 | 192 |
|
176 | 193 | Generics
|
@@ -316,6 +333,43 @@ User defined generic type aliases are also supported. Examples::
|
316 | 333 | .. versionchanged:: 3.7
|
317 | 334 | :class:`Generic` no longer has a custom metaclass.
|
318 | 335 |
|
| 336 | +User-defined generics for parameter expressions are also supported via parameter |
| 337 | +specification variables in the form ``Generic[P]``. The behavior is consistent |
| 338 | +with type variables' described above as parameter specification variables are |
| 339 | +treated by the typing module as a specialized type variable. The one exception |
| 340 | +to this is that a list of types can be used to substitute a :class:`ParamSpec`:: |
| 341 | + |
| 342 | + >>> from typing import Generic, ParamSpec, TypeVar |
| 343 | + |
| 344 | + >>> T = TypeVar('T') |
| 345 | + >>> P = ParamSpec('P') |
| 346 | + |
| 347 | + >>> class Z(Generic[T, P]): ... |
| 348 | + ... |
| 349 | + >>> Z[int, [dict, float]] |
| 350 | + __main__.Z[int, (<class 'dict'>, <class 'float'>)] |
| 351 | + |
| 352 | + |
| 353 | +Furthermore, a generic with only one parameter specification variable will accept |
| 354 | +parameter lists in the forms ``X[[Type1, Type2, ...]]`` and also |
| 355 | +``X[Type1, Type2, ...]`` for aesthetic reasons. Internally, the latter is converted |
| 356 | +to the former and are thus equivalent:: |
| 357 | + |
| 358 | + >>> class X(Generic[P]): ... |
| 359 | + ... |
| 360 | + >>> X[int, str] |
| 361 | + __main__.X[(<class 'int'>, <class 'str'>)] |
| 362 | + >>> X[[int, str]] |
| 363 | + __main__.X[(<class 'int'>, <class 'str'>)] |
| 364 | + |
| 365 | +Do note that generics with :class:`ParamSpec` may not have correct |
| 366 | +``__parameters__`` after substitution in some cases because they |
| 367 | +are intended primarily for static type checking. |
| 368 | + |
| 369 | +.. versionchanged:: 3.10 |
| 370 | + :class:`Generic` can now be parameterized over parameter expressions. |
| 371 | + See :class:`ParamSpec` and :pep:`612` for more details. |
| 372 | + |
319 | 373 | A user-defined generic class can have ABCs as base classes without a metaclass
|
320 | 374 | conflict. Generic metaclasses are not supported. The outcome of parameterizing
|
321 | 375 | generics is cached, and most types in the typing module are hashable and
|
@@ -602,10 +656,80 @@ These can be used as types in annotations using ``[]``, each having a unique syn
|
602 | 656 | ``Callable[..., Any]``, and in turn to
|
603 | 657 | :class:`collections.abc.Callable`.
|
604 | 658 |
|
| 659 | + Callables which take other callables as arguments may indicate that their |
| 660 | + parameter types are dependent on each other using :class:`ParamSpec`. |
| 661 | + Additionally, if that callable adds or removes arguments from other |
| 662 | + callables, the :data:`Concatenate` operator may be used. They |
| 663 | + take the form ``Callable[ParamSpecVariable, ReturnType]`` and |
| 664 | + ``Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]`` |
| 665 | + respectively. |
| 666 | + |
605 | 667 | .. deprecated:: 3.9
|
606 | 668 | :class:`collections.abc.Callable` now supports ``[]``. See :pep:`585` and
|
607 | 669 | :ref:`types-genericalias`.
|
608 | 670 |
|
| 671 | + .. versionchanged:: 3.10 |
| 672 | + ``Callable`` now supports :class:`ParamSpec` and :data:`Concatenate`. |
| 673 | + See :pep:`612` for more information. |
| 674 | + |
| 675 | + .. seealso:: |
| 676 | + The documentation for :class:`ParamSpec` and :class:`Concatenate` provide |
| 677 | + examples of usage with ``Callable``. |
| 678 | + |
| 679 | +.. data:: Concatenate |
| 680 | + |
| 681 | + Used with :data:`Callable` and :class:`ParamSpec` to type annotate a higher |
| 682 | + order callable which adds, removes, or transforms parameters of another |
| 683 | + callable. Usage is in the form |
| 684 | + ``Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]``. ``Concatenate`` |
| 685 | + is currently only valid when used as the first argument to a :data:`Callable`. |
| 686 | + The last parameter to ``Concatenate`` must be a :class:`ParamSpec`. |
| 687 | + |
| 688 | + For example, to annotate a decorator ``with_lock`` which provides a |
| 689 | + :class:`threading.Lock` to the decorated function, ``Concatenate`` can be |
| 690 | + used to indicate that ``with_lock`` expects a callable which takes in a |
| 691 | + ``Lock`` as the first argument, and returns a callable with a different type |
| 692 | + signature. In this case, the :class:`ParamSpec` indicates that the returned |
| 693 | + callable's parameter types are dependent on the parameter types of the |
| 694 | + callable being passed in:: |
| 695 | + |
| 696 | + from collections.abc import Callable |
| 697 | + from threading import Lock |
| 698 | + from typing import Any, Concatenate, ParamSpec |
| 699 | + |
| 700 | + P = ParamSpec('P') |
| 701 | + R = ParamSpec('R') |
| 702 | + |
| 703 | + # Use this lock to ensure that only one thread is executing a function |
| 704 | + # at any time. |
| 705 | + my_lock = Lock() |
| 706 | + |
| 707 | + def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: |
| 708 | + '''A type-safe decorator which provides a lock.''' |
| 709 | + global my_lock |
| 710 | + def inner(*args: P.args, **kwargs: P.kwargs) -> T: |
| 711 | + # Provide the lock as the first argument. |
| 712 | + return f(my_lock, *args, **kwargs) |
| 713 | + return inner |
| 714 | + |
| 715 | + @with_lock |
| 716 | + def sum_threadsafe(lock: Lock, numbers: list[float]) -> float: |
| 717 | + '''Add a list of numbers together in a thread-safe manner.''' |
| 718 | + with lock: |
| 719 | + return sum(numbers) |
| 720 | + |
| 721 | + # We don't need to pass in the lock ourselves thanks to the decorator. |
| 722 | + sum_threadsafe([1.1, 2.2, 3.3]) |
| 723 | + |
| 724 | +.. versionadded:: 3.10 |
| 725 | + |
| 726 | +.. seealso:: |
| 727 | + |
| 728 | + * :pep:`612` -- Parameter Specification Variables (the PEP which introduced |
| 729 | + ``ParamSpec`` and ``Concatenate``). |
| 730 | + * :class:`ParamSpec` and :class:`Callable`. |
| 731 | + |
| 732 | + |
609 | 733 | .. class:: Type(Generic[CT_co])
|
610 | 734 |
|
611 | 735 | A variable annotated with ``C`` may accept a value of type ``C``. In
|
@@ -876,6 +1000,84 @@ These are not used in annotations. They are building blocks for creating generic
|
876 | 1000 | for the type variable must be a subclass of the boundary type,
|
877 | 1001 | see :pep:`484`.
|
878 | 1002 |
|
| 1003 | +.. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False) |
| 1004 | + |
| 1005 | + Parameter specification variable. A specialized version of |
| 1006 | + :class:`type variables <TypeVar>`. |
| 1007 | + |
| 1008 | + Usage:: |
| 1009 | + |
| 1010 | + P = ParamSpec('P') |
| 1011 | + |
| 1012 | + Parameter specification variables exist primarily for the benefit of static |
| 1013 | + type checkers. They are used to forward the parameter types of one |
| 1014 | + callable to another callable -- a pattern commonly found in higher order |
| 1015 | + functions and decorators. They are only valid when used in ``Concatenate``, |
| 1016 | + or as the first argument to ``Callable``, or as parameters for user-defined |
| 1017 | + Generics. See :class:`Generic` for more information on generic types. |
| 1018 | + |
| 1019 | + For example, to add basic logging to a function, one can create a decorator |
| 1020 | + ``add_logging`` to log function calls. The parameter specification variable |
| 1021 | + tells the type checker that the callable passed into the decorator and the |
| 1022 | + new callable returned by it have inter-dependent type parameters:: |
| 1023 | + |
| 1024 | + from collections.abc import Callable |
| 1025 | + from typing import TypeVar, ParamSpec |
| 1026 | + import logging |
| 1027 | + |
| 1028 | + T = TypeVar('T') |
| 1029 | + P = ParamSpec('P') |
| 1030 | + |
| 1031 | + def add_logging(f: Callable[P, T]) -> Callable[P, T]: |
| 1032 | + '''A type-safe decorator to add logging to a function.''' |
| 1033 | + def inner(*args: P.args, **kwargs: P.kwargs) -> T: |
| 1034 | + logging.info(f'{f.__name__} was called') |
| 1035 | + return f(*args, **kwargs) |
| 1036 | + return inner |
| 1037 | + |
| 1038 | + @add_logging |
| 1039 | + def add_two(x: float, y: float) -> float: |
| 1040 | + '''Add two numbers together.''' |
| 1041 | + return x + y |
| 1042 | + |
| 1043 | + Without ``ParamSpec``, the simplest way to annotate this previously was to |
| 1044 | + use a :class:`TypeVar` with bound ``Callable[..., Any]``. However this |
| 1045 | + causes two problems: |
| 1046 | + |
| 1047 | + 1. The type checker can't type check the ``inner`` function because |
| 1048 | + ``*args`` and ``**kwargs`` have to be typed :data:`Any`. |
| 1049 | + 2. :func:`~cast` may be required in the body of the ``add_logging`` |
| 1050 | + decorator when returning the ``inner`` function, or the static type |
| 1051 | + checker must be told to ignore the ``return inner``. |
| 1052 | + |
| 1053 | + .. attribute:: args |
| 1054 | + .. attribute:: kwargs |
| 1055 | + |
| 1056 | + Since ``ParamSpec`` captures both positional and keyword parameters, |
| 1057 | + ``P.args`` and ``P.kwargs`` can be used to split a ``ParamSpec`` into its |
| 1058 | + components. ``P.args`` represents the tuple of positional parameters in a |
| 1059 | + given call and should only be used to annotate ``*args``. ``P.kwargs`` |
| 1060 | + represents the mapping of keyword parameters to their values in a given call, |
| 1061 | + and should be only be used to annotate ``**kwargs`` or ``**kwds``. Both |
| 1062 | + attributes require the annotated parameter to be in scope. |
| 1063 | + |
| 1064 | + Parameter specification variables created with ``covariant=True`` or |
| 1065 | + ``contravariant=True`` can be used to declare covariant or contravariant |
| 1066 | + generic types. The ``bound`` argument is also accepted, similar to |
| 1067 | + :class:`TypeVar`. However the actual semantics of these keywords are yet to |
| 1068 | + be decided. |
| 1069 | + |
| 1070 | + .. versionadded:: 3.10 |
| 1071 | + |
| 1072 | + .. note:: |
| 1073 | + Only parameter specification variables defined in global scope can |
| 1074 | + be pickled. |
| 1075 | + |
| 1076 | + .. seealso:: |
| 1077 | + * :pep:`612` -- Parameter Specification Variables (the PEP which introduced |
| 1078 | + ``ParamSpec`` and ``Concatenate``). |
| 1079 | + * :class:`Callable` and :class:`Concatenate`. |
| 1080 | + |
879 | 1081 | .. data:: AnyStr
|
880 | 1082 |
|
881 | 1083 | ``AnyStr`` is a type variable defined as
|
|
0 commit comments