Сообщить об ошибке.

Тип аннотации TypeVar модуля typing в Python

Типизация универсальных значений переменных

Не используется в аннотациях, являются строительным блоком для создания универсальных типов.

Синтаксис:

from typing import TypeVar

typing.TypeVar(name, *constraints, bound=None, covariant=False, 
               contravariant=False, infer_variance=False)

Параметры:

  • name - имя переменной типа,
  • *constraints - кортеж, содержащий ограничения переменной типа, если таковые имеются,
  • bound=None - подтип/привязка переменной типа, если такой имеется,
  • covariant=False - был ли тип переменной явно помечен как ковариантный,
  • contravariant=False - был ли тип переменной явно помечен как контравариантный,
  • infer_variance=False - следует ли определять отклонение переменной типа с помощью средств проверки типов.

Описание TypeVar() :

Тип аннотации TypeVar() модуля typing представляет собой - возможные типы переменных.

Предпочтительным способом создания переменной типа в Python 3.12 является использование специального синтаксиса для универсальных функций, универсальных классов и псевдонимов универсальных типов:

# T - это `TypeVar`
class Sequence[T]:
    ...

Этот синтаксис также можно использовать для создания переменных связанного и ограниченного типа:

# S - это `TypeVar`, привязанный к `str`
class StrSequence[S: str]:
    ...
# A - это `TypeVar`, ограниченный значением `str` или `bytes`
class StrOrBytesSequence[A: (str, bytes)]:
    ...

При желании и для совместимости с _Python<=3.12_, переменные типа многократного использования можно создать вручную, например:

T = TypeVar('T')  # Может быть что угодно
A = TypeVar('A', str, bytes)  # Должно быть `str` или `bytes`
S = TypeVar('S', bound=str)  # Может быть любым подтипом `str`

Переменные типа существуют в первую очередь для целей проверки статических типов. Они служат параметрами для универсальных типов, а также для определений универсальных функций и псевдонимов типов. Дополнительно смотрите сведения о типе аннотации typing.Generic.

Универсальные функции работают следующим образом:

def repeat[T](x: T, n: int) -> Sequence[T]:
    """Возвращает список, содержащий n ссылок на x."""
    return [x]*n

def print_capitalized[S: str](x: S) -> S:
    """Печатает x с заглавной буквы и возвращает x."""
    print(x.capitalize())
    return x

def concatenate[A: (str, bytes)](x: A, y: A) -> A:
    """Конкатенация двух объектов `strings` или `bytes`."""
    return x + y

Обратите внимание, что переменные типа могут быть связанными, ограниченными или ни одним из них, но не могут быть одновременно связанными и ограниченными.

Отклонения переменных типа определяется средствами проверки типов, когда они создаются с помощью синтаксиса параметра типа или когда передается infer_variance=True. Созданные вручную переменные типа могут быть явно помечены как ковариантные или контравариантные путем передачи covariant=True или contravariant=True. По умолчанию переменные типа, созданные вручную, являются инвариантными.

Переменные связанного типа и переменные ограниченного типа имеют разную семантику по нескольким важным причинам. Использование переменной связанного типа означает, что TypeVar будет решен с использованием наиболее конкретного возможного типа:

x = print_capitalized('a string')
# выявленный тип - `str`
reveal_type(x)

class StringSubclass(str):
    pass

y = print_capitalized(StringSubclass('another string'))
# выявленный тип - StringSubclass
reveal_type(y)

# ошибка: `int` не является подтипом `str`
z = print_capitalized(45)

Переменные типа могут быть привязаны к конкретным типам, абстрактным типам (ABC или протоколам) и даже к объединениям типов:

# Может быть чем угодно с помощью метода `__abs__`
def print_abs[T: SupportsAbs](arg: T) -> None:
    print("Absolute value:", abs(arg))

# Может быть любым подтипом объединения `str|bytes`
U = TypeVar('U', bound=str|bytes) 
# Может быть что угодно с помощью метода `__abs__`
V = TypeVar('V', bound=SupportsAbs)

Однако использование переменной ограниченного типа означает, что TypeVar может быть решен только как одно из заданных ограничений:

a = concatenate('one', 'two')
# выявленный тип - `str`
reveal_type(a)

b = concatenate(StringSubclass('one'), StringSubclass('two'))
# выявленный тип - `str`, несмотря на передачу `StringSubclass`
reveal_type(b)

# ошибка: переменная типа 'A' в вызове функции может быть  
# либо строкой, либо байтами , но не обоими одновременно
c = concatenate('one', b'two')

Во время выполнения isinstance(x, T) вызовет TypeError.

Во время выполнения, isinstance(x, T) вызовет TypeError.

__name__:

Имя переменной типа.

__covariant__:

Является ли переменная типа явно помеченной как ковариантная.

__contravariant__:

Является ли переменная типа явно помеченной как контравариантная.

__infer_variance__:

Должна ли дисперсия переменной типа выводиться проверяющими типы.

Добавлено в Python 3.12.

__bound__:

Верхняя граница переменной типа, если есть.

Изменено в Python 3.12: Для переменных типа, созданных через синтаксис параметров типа, граница вычисляется только при доступе к атрибуту, а не при создании переменной типа (см. Ленивое вычисление).

evaluate_bound():

Функция вычисления, соответствующая атрибуту __bound__. При прямом вызове этот метод поддерживает только формат VALUE, что эквивалентно прямому доступу к атрибуту __bound__, но объект метода может быть передан в annotationlib.call_evaluate_function() для вычисления значения в другом формате.

Добавлено в Python 3.14.

__constraints__:

Кортеж, содержащий ограничения переменной типа, если есть.

Изменено в Python 3.12: Для переменных типа, созданных через синтаксис параметров типа, ограничения вычисляются только при доступе к атрибуту, а не при создании переменной типа (см. Ленивое вычисление).

evaluate_constraints():

Функция вычисления, соответствующая атрибуту __constraints__. При прямом вызове этот метод поддерживает только формат VALUE, что эквивалентно прямому доступу к атрибуту __constraints__, но объект метода может быть передан в annotationlib.call_evaluate_function() для вычисления значения в другом формате.

Добавлено в Python 3.14.

__default__:

Значение по умолчанию переменной типа, или typing.NoDefault, если оно отсутствует.

Добавлено в Python 3.13.

evaluate_default():

Функция вычисления, соответствующая атрибуту __default__. При прямом вызове этот метод поддерживает только формат VALUE, что эквивалентно прямому доступу к атрибуту __default__, но объект метода может быть передан в annotationlib.call_evaluate_function() для вычисления значения в другом формате.

Добавлено в Python 3.14.

has_default():

Возвращает, имеет ли переменная типа значение по умолчанию. Это эквивалентно проверке того, что __default__ не является синглтоном typing.NoDefault, за исключением того, что это не приводит к вычислению лениво вычисленного значения по умолчанию.

Добавлено в Python 3.13.


Изменено в Python 3.12: переменные типа теперь можно объявлять с использованием синтаксиса параметра типа. Был добавлен параметр infer_variance.

Изменено в Python 3.13: Добавлена ​​поддержка значений по умолчанию.