type_params ::= "[" type_param ("," type_param)* "]"
type_param ::= typevar | typevartuple | paramspec
typevar ::= identifier (":" expression)?
typevartuple ::= "*" identifier
paramspec ::= "**" identifier
Новое в Python 3.12.
Функции (включая сопрограммы), классы и псевдонимы типов могут содержать список параметров типа:
def max[T](args: list[T]) -> T: ... async def amax[T](args: list[T]) -> T: ... class Bag[T]: def __iter__(self) -> Iterator[T]: ... def add(self, arg: T) -> None: ... type ListOrSet[T] = list[T] | set[T]
Семантически это указывает на то, что функция, класс или псевдоним типа являются универсальными для переменной типа. Эта информация в основном используется средствами проверки статических типов, и во время выполнения универсальные объекты ведут себя так же, как их неуниверсальные аналоги.
Параметры типа объявляются в квадратных скобках ([]
) сразу после имени функции, класса или псевдонима типа. Параметры типа доступны в пределах области видимости универсального объекта, но не где-либо еще. Таким образом, после объявления def func[T](): pass
имя T
недоступно в области видимости модуля. Область действия параметров типа моделируется с помощью специальной функции (технически области видимости аннотации), которая завершает создание универсального объекта.
Универсальные функции, классы и псевдонимы типов имеют атрибут TypeAliasType.__type_params__
, в котором перечислены их параметры типа.
Параметры типа бывают трех видов:
typing.TypeVar
, представленный простым именем (например, T
). Семантически это представляет один тип для средства проверки типов.typing.TypeVarTuple
, представленный именем с префиксом одной звездочки (например, *Ts
). Семантически это обозначает кортеж любого числа типов.typing.ParamSpec
, представленный именем с префиксом двух звездочек (например, **P
). Семантически это обозначает аргументы вызываемого объекта.Объявления typing.TypeVar
могут определять границы и ограничения с помощью двоеточия (:
), за которым следует выражение. Одиночное выражение после двоеточия указывает на границу (например, T: int
). Семантически это означает, что typing.TypeVar
может представлять только типы, которые являются подтипом этой границы. Кортеж выражений в скобках после двоеточия указывает на набор ограничений (например, T: (str, bytes)
). Каждый член кортежа должен быть типом (опять же, это не применяется во время выполнения). Переменные ограниченного типа могут принимать только один из типов в списке ограничений.
Для typing.TypeVar
, объявленного с использованием синтаксиса списка параметров типа, привязка и ограничения не оцениваются при создании универсального объекта, а только тогда, когда к значению осуществляется явный доступ через атрибуты TypeVar.__bound__
и TypeVar.__constraints__
. Для этого границы или ограничения оцениваются в отдельной области видимости аннотаций.
Типы параметров typing.TypeVarTuple
и typing.ParamSpec
не могут иметь границ или ограничений.
В следующем примере показан полный набор разрешенных объявлений параметров типа:
def overly_generic[ SimpleTypeVar, TypeVarWithBound: int, TypeVarWithConstraints: (str, bytes), *SimpleTypeVarTuple, **SimpleParamSpec, ]( a: SimpleTypeVar, b: TypeVarWithBound, c: Callable[SimpleParamSpec, TypeVarWithConstraints], *d: SimpleTypeVarTuple, ): ...