Не используется в аннотациях, являются строительным блоком для создания универсальных типов.
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
.
TypeVar.__name__
: имя переменной типа.
TypeVar.__covariant__
: был ли тип переменной явно помечен как ковариантный.
TypeVar.__contravariant__
: был ли тип переменной явно помечен как контравариантный.
TypeVar.__infer_variance__
: следует ли определять отклонение переменной типа с помощью средств проверки типов.
Новое в Python 3.12.
TypeVar.__bound__
: подтип/привязка переменной типа, если таковая имеется.
Изменено в Python 3.12: Для переменных типа, созданных с помощью синтаксиса параметра типа, привязка вычисляется только при обращении к атрибуту, а не при создании переменной типа.
TypeVar.__constraints__
: кортеж, содержащий ограничения переменной типа, если таковые имеются.
Изменено в Python 3.12: Для переменных типа, созданных с помощью синтаксиса параметра типа, ограничения вычисляются только при обращении к атрибуту, а не при создании переменной типа.
Изменено в Python 3.12: переменные типа теперь можно объявлять с использованием синтаксиса параметра типа. Был добавлен параметр
infer_variance
.