typing
— Поддержка подсказок типов¶
Added in version 3.5.
Источник: Lib/typing.py
Примечание
Время выполнения Python не принуждает к использованию аннотаций типов функций и переменных. Они могут использоваться сторонними инструментами, такими как type checkers, IDE, линтеры и т. д.
Этот модуль обеспечивает поддержку подсказок типов во время выполнения.
Рассмотрим функцию ниже:
def moon_weight(earth_weight: float) -> str:
return f'On the moon, you would weigh {earth_weight * 0.166} kilograms.'
Функция moon_weight
принимает аргумент, который должен быть экземпляром float
, на что указывает подсказка тип earth_weight: float
. Ожидается, что функция вернет экземпляр str
, на что указывает подсказка -> str
.
Хотя подсказки типов могут быть простыми классами, такими как float
или str
, они могут быть и более сложными. Модуль typing
предоставляет словарь более сложных подсказок типов.
В модуль typing
часто добавляются новые возможности. Пакет typing_extensions обеспечивает обратный перенос этих новых возможностей на старые версии Python.
См.также
- «Typing cheat sheet»
Краткий обзор подсказок типов (размещено в документации mypy)
- Раздел «Справочник по системе типов» в the mypy docs
Система типизации Python стандартизирована через PEP, поэтому эта ссылка должна быть применима к большинству программ проверки типов Python. (Некоторые части могут быть специфичны для mypy).
- «Static Typing with Python»
Документация, не требующая проверки типов, написанная сообществом, в которой подробно описываются возможности системы типов, полезные инструменты, связанные с типизацией, и лучшие практики типизации.
Спецификация системы типов Python¶
Каноническую, актуальную спецификацию системы типов Python можно найти по адресу «Specification for the Python type system».
Псевдонимы типа¶
Псевдоним типа задается с помощью оператора type
, который создает экземпляр TypeAliasType
. В этом примере Vector
и list[float]
будут эквивалентно восприниматься статическими программами проверки типов:
type Vector = list[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
# passes type checking; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])
Псевдонимы типов полезны для упрощения сложных сигнатур типов. Например:
from collections.abc import Sequence
type ConnectionOptions = dict[str, str]
type Address = tuple[str, int]
type Server = tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Sequence[Server]) -> None:
...
# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
message: str,
servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:
...
Оператор type
является новым в Python 3.12. Для обратной совместимости псевдонимы типов также можно создавать с помощью простого присваивания:
Vector = list[float]
Или пометить TypeAlias
, чтобы явно указать, что это псевдоним типа, а не обычное присваивание переменной:
from typing import TypeAlias
Vector: TypeAlias = list[float]
NewType¶
Используйте помощник NewType
для создания отдельных типов:
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
Программа проверки статических типов будет относиться к новому типу так, как если бы он был подклассом исходного типа. Это полезно для выявления логических ошибок:
def get_user_name(user_id: UserId) -> str:
...
# passes type checking
user_a = get_user_name(UserId(42351))
# fails type checking; an int is not a UserId
user_b = get_user_name(-1)
Вы по-прежнему можете выполнять все операции int
над переменной типа UserId
, но результат всегда будет иметь тип int
. Это позволяет передавать UserId
туда, где можно было бы ожидать int
, но не позволит вам случайно создать UserId
недопустимым способом:
# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)
Обратите внимание, что эти проверки выполняются только статической программой проверки типов. Во время выполнения выражение Derived = NewType('Derived', Base)
сделает Derived
вызываемой функцией, которая немедленно вернет любой переданный ей параметр. Это означает, что выражение Derived(some_value)
не создает новый класс и не влечет за собой больших накладных расходов, чем обычный вызов функции.
Точнее, выражение some_value is Derived(some_value)
всегда истинно во время выполнения.
Недопустимо создавать подтип Derived
:
from typing import NewType
UserId = NewType('UserId', int)
# Fails at runtime and does not pass type checking
class AdminUserId(UserId): pass
Однако можно создать NewType
на основе «производного» NewType
:
from typing import NewType
UserId = NewType('UserId', int)
ProUserId = NewType('ProUserId', UserId)
и проверка типов для ProUserId
будет работать, как и ожидалось.
Более подробную информацию см. в разделе PEP 484.
Примечание
Вспомните, что использование псевдонима типа объявляет два типа эквивалентными друг другу. Если сделать type Alias = Original
, то статическая проверка типов будет рассматривать Alias
как точно эквивалентный Original
во всех случаях. Это полезно, когда вы хотите упростить сложные сигнатуры типов.
Напротив, NewType
объявляет один тип подтипом другого. Если сделать Derived = NewType('Derived', Original)
, то статическая проверка типов будет рассматривать Derived
как подкласс Original
, что означает, что значение типа Original
не может быть использовано там, где ожидается значение типа Derived
. Это полезно, когда вы хотите предотвратить логические ошибки с минимальными затратами времени выполнения.
Added in version 3.5.2.
Изменено в версии 3.10: NewType
теперь является классом, а не функцией. В результате при вызове NewType
вместо обычной функции возникают дополнительные затраты времени выполнения.
Изменено в версии 3.11: Производительность вызова NewType
была восстановлена до уровня Python 3.9.
Аннотирование вызываемых объектов¶
Функции - или другие объекты callable - могут быть аннотированы с помощью collections.abc.Callable
или typing.Callable
. Callable[[int], str]
обозначает функцию, которая принимает один параметр типа int
и возвращает str
.
Например:
from collections.abc import Callable, Awaitable
def feeder(get_next_item: Callable[[], str]) -> None:
... # Body
def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
... # Body
async def on_update(value: str) -> None:
... # Body
callback: Callable[[str], Awaitable[None]] = on_update
Синтаксис подписки всегда должен использоваться ровно с двумя значениями: списком аргументов и возвращаемым типом. Список аргументов должен быть списком типов, символами ParamSpec
, Concatenate
или многоточием. Возвращаемый тип должен быть одним типом.
Если в качестве списка аргументов указано буквенное многоточие ...
, это означает, что допустим вызываемый модуль с любым произвольным списком параметров:
def concat(x: str, y: str) -> str:
return x + y
x: Callable[..., str]
x = str # OK
x = concat # Also OK
Callable
не может выражать сложные сигнатуры, такие как функции, принимающие переменное число аргументов, overloaded functions или функции, имеющие параметры только с ключевыми словами. Однако эти сигнатуры можно выразить, определив класс Protocol
с методом __call__()
:
from collections.abc import Iterable
from typing import Protocol
class Combiner(Protocol):
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...
def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
for item in data:
...
def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
...
batch_proc([], good_cb) # OK
batch_proc([], bad_cb) # Error! Argument 2 has incompatible type because of
# different name and kind in the callback
Вызываемые модули, принимающие в качестве аргументов другие вызываемые модули, могут указать, что типы их параметров зависят друг от друга, используя оператор ParamSpec
. Кроме того, если вызываемая переменная добавляет или удаляет аргументы из других вызываемых переменных, можно использовать оператор Concatenate
. Они имеют форму Callable[ParamSpecVariable, ReturnType]
и Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
соответственно.
Изменено в версии 3.10: Callable
теперь поддерживает ParamSpec
и Concatenate
. Более подробную информацию см. в разделе PEP 612.
См.также
В документации к ParamSpec
и Concatenate
приведены примеры использования в Callable
.
Дженерики¶
Поскольку информация о типах объектов, хранящихся в контейнерах, не может быть статически выведена общим способом, многие контейнерные классы в стандартной библиотеке поддерживают подписку для обозначения ожидаемых типов элементов контейнера.
from collections.abc import Mapping, Sequence
class Employee: ...
# Sequence[Employee] indicates that all elements in the sequence
# must be instances of "Employee".
# Mapping[str, str] indicates that all keys and all values in the mapping
# must be strings.
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
Общие функции и классы можно параметризовать с помощью type parameter syntax:
from collections.abc import Sequence
def first[T](l: Sequence[T]) -> T: # Function is generic over the TypeVar "T"
return l[0]
Или используя фабрику TypeVar
напрямую:
from collections.abc import Sequence
from typing import TypeVar
U = TypeVar('U') # Declare type variable "U"
def second(l: Sequence[U]) -> U: # Function is generic over the TypeVar "U"
return l[1]
Изменено в версии 3.12: В Python 3.12 появилась синтаксическая поддержка дженериков.
Аннотирование кортежей¶
Для большинства контейнеров в Python система типизации предполагает, что все элементы в контейнере будут иметь один и тот же тип. Например:
from collections.abc import Mapping
# Type checker will infer that all elements in ``x`` are meant to be ints
x: list[int] = []
# Type checker error: ``list`` only accepts a single type argument:
y: list[int, str] = [1, 'foo']
# Type checker will infer that all keys in ``z`` are meant to be strings,
# and that all values in ``z`` are meant to be either strings or ints
z: Mapping[str, str | int] = {}
list
принимает только один аргумент типа, поэтому программа проверки типов выдаст ошибку на приведенном выше присваивании y
. Аналогично, Mapping
принимает только два аргумента типа: первый указывает на тип ключей, а второй - на тип значений.
Однако, в отличие от большинства других контейнеров Python, в идиоматическом коде Python кортежи часто содержат элементы, которые не все имеют одинаковый тип. По этой причине кортежи имеют особый тип в системе типизации Python. tuple
принимает любое количество аргументов типа:
# OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int
x: tuple[int] = (5,)
# OK: ``y`` is assigned to a tuple of length 2;
# element 1 is an int, element 2 is a str
y: tuple[int, str] = (5, "foo")
# Error: the type annotation indicates a tuple of length 1,
# but ``z`` has been assigned to a tuple of length 3
z: tuple[int] = (1, 2, 3)
Для обозначения кортежа, который может быть любой длины, и в котором все элементы имеют одинаковый тип T
, используйте tuple[T, ...]
. Для обозначения пустого кортежа используйте tuple[()]
. Использование простого tuple
в качестве аннотации эквивалентно использованию tuple[Any, ...]
:
x: tuple[int, ...] = (1, 2)
# These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
x = (1, 2, 3)
x = ()
# This reassignment is an error: all elements in ``x`` must be ints
x = ("foo", "bar")
# ``y`` can only ever be assigned to an empty tuple
y: tuple[()] = ()
z: tuple = ("foo", "bar")
# These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
z = (1, 2, 3)
z = ()
Тип объектов класса¶
Переменная, аннотированная C
, может принимать значение типа C
. Напротив, переменная, аннотированная type[C]
(или typing.Type[C]
), может принимать значения, которые сами являются классами - в частности, она будет принимать классовый объект типа C
. Например:
a = 3 # Has type ``int``
b = int # Has type ``type[int]``
c = type(a) # Also has type ``type[int]``
Обратите внимание, что type[C]
ковариантен:
class User: ...
class ProUser(User): ...
class TeamUser(User): ...
def make_new_user(user_class: type[User]) -> User:
# ...
return user_class()
make_new_user(User) # OK
make_new_user(ProUser) # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser) # Still fine
make_new_user(User()) # Error: expected ``type[User]`` but got ``User``
make_new_user(int) # Error: ``type[int]`` is not a subtype of ``type[User]``
Единственными допустимыми параметрами для type
являются классы, Any
, type variables и объединения любого из этих типов. Например:
def new_non_team_user(user_class: type[BasicUser | ProUser]): ...
new_non_team_user(BasicUser) # OK
new_non_team_user(ProUser) # OK
new_non_team_user(TeamUser) # Error: ``type[TeamUser]`` is not a subtype
# of ``type[BasicUser | ProUser]``
new_non_team_user(User) # Also an error
type[Any]
эквивалентен type
, который является корнем из metaclass hierarchy в Python.
Определяемые пользователем общие типы¶
Определяемый пользователем класс может быть определен как общий класс.
from logging import Logger
class LoggedVar[T]:
def __init__(self, value: T, name: str, logger: Logger) -> None:
self.name = name
self.logger = logger
self.value = value
def set(self, new: T) -> None:
self.log('Set ' + repr(self.value))
self.value = new
def get(self) -> T:
self.log('Get ' + repr(self.value))
return self.value
def log(self, message: str) -> None:
self.logger.info('%s: %s', self.name, message)
Этот синтаксис указывает на то, что класс LoggedVar
параметризован вокруг единственного type variable T
. Это также делает T
допустимым типом в теле класса.
Родовые классы неявно наследуют от Generic
. Для совместимости с Python 3.11 и ниже, можно также явно наследовать от Generic
, чтобы указать на общий класс:
from typing import TypeVar, Generic
T = TypeVar('T')
class LoggedVar(Generic[T]):
...
У общих классов есть методы __class_getitem__()
, то есть они могут быть параметризованы во время выполнения (например, LoggedVar[int]
ниже):
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
Родовой тип может иметь любое количество переменных типа. В качестве параметров общего типа допустимы все разновидности TypeVar
:
from typing import TypeVar, Generic, Sequence
class WeirdTrio[T, B: Sequence[bytes], S: (int, str)]:
...
OldT = TypeVar('OldT', contravariant=True)
OldB = TypeVar('OldB', bound=Sequence[bytes], covariant=True)
OldS = TypeVar('OldS', int, str)
class OldWeirdTrio(Generic[OldT, OldB, OldS]):
...
Каждый аргумент переменной типа в Generic
должен быть отдельным. Таким образом, это неверно:
from typing import TypeVar, Generic
...
class Pair[M, M]: # SyntaxError
...
T = TypeVar('T')
class Pair(Generic[T, T]): # INVALID
...
Общие классы также могут наследоваться от других классов:
from collections.abc import Sized
class LinkedList[T](Sized):
...
При наследовании от общих классов некоторые параметры типа могут быть исправлены:
from collections.abc import Mapping
class MyDict[T](Mapping[str, T]):
...
В данном случае MyDict
имеет единственный параметр, T
.
Использование родового класса без указания параметров типа предполагает наличие Any
для каждой позиции. В следующем примере MyIterable
не является родовым, но неявно наследуется от Iterable[Any]
:
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
...
Также поддерживаются псевдонимы общих типов, определяемые пользователем. Примеры:
from collections.abc import Iterable
type Response[S] = Iterable[S] | int
# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
...
type Vec[T] = Iterable[tuple[T, T]]
def inproduct[T: (int, float, complex)](v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
return sum(x*y for x, y in v)
Для обратной совместимости псевдонимы общих типов также могут быть созданы с помощью простого присваивания:
from collections.abc import Iterable
from typing import TypeVar
S = TypeVar("S")
Response = Iterable[S] | int
Изменено в версии 3.7: У Generic
больше нет пользовательского метакласса.
Изменено в версии 3.12: В версии 3.12 появилась синтаксическая поддержка дженериков и псевдонимов типов. Ранее родовые классы должны были явно наследоваться от Generic
или содержать переменную типа в одной из своих основ.
Определяемые пользователем родословные для выражений параметров также поддерживаются через переменные спецификации параметров в форме [**P]
. Поведение соответствует описанному выше поведению переменных типов, поскольку переменные спецификации параметров рассматриваются модулем типизации как специализированные переменные типов. Единственным исключением из этого является то, что список типов может быть использован для замены ParamSpec
:
>>> class Z[T, **P]: ... # T is a TypeVar; P is a ParamSpec
...
>>> Z[int, [dict, float]]
__main__.Z[int, [dict, float]]
Классы, общие для ParamSpec
, также могут быть созданы с помощью явного наследования от Generic
. В этом случае **
не используется:
from typing import ParamSpec, Generic
P = ParamSpec('P')
class Z(Generic[P]):
...
Еще одно различие между TypeVar
и ParamSpec
заключается в том, что дженерик с одной переменной спецификации параметров будет принимать списки параметров в форме X[[Type1, Type2, ...]]
, а также X[Type1, Type2, ...]
по эстетическим соображениям. Внутри языка последняя форма преобразуется в первую, так что следующие варианты эквивалентны:
>>> class X[**P]: ...
...
>>> X[int, str]
__main__.X[[int, str]]
>>> X[[int, str]]
__main__.X[[int, str]]
Обратите внимание, что дженерики с ParamSpec
в некоторых случаях могут не иметь корректных __parameters__
после подстановки, поскольку они предназначены в первую очередь для статической проверки типов.
Изменено в версии 3.10: Generic
теперь можно параметризовать через выражения параметров. Более подробную информацию см. в разделах ParamSpec
и PEP 612.
Определенный пользователем общий класс может иметь ABC в качестве базового класса без конфликта с метаклассом. Родовые метаклассы не поддерживаются. Результат параметризации дженериков кэшируется, а большинство типов в модуле типизации являются hashable и сравнимы по равенству.
Тип Any
¶
Особым типом является Any
. Статическая программа проверки типов будет рассматривать каждый тип как совместимый с Any
, а Any
- как совместимый с любым типом.
Это означает, что над значением типа Any
можно выполнить любую операцию или вызов метода и присвоить его любой переменной:
from typing import Any
a: Any = None
a = [] # OK
a = 2 # OK
s: str = ''
s = a # OK
def foo(item: Any) -> int:
# Passes type checking; 'item' could be any type,
# and that type might have a 'bar' method
item.bar()
...
Обратите внимание, что при присвоении значения типа Any
более точному типу проверка типов не выполняется. Например, статическая проверка типов не сообщила об ошибке при присвоении a
типу s
, хотя s
был объявлен как тип str
и во время выполнения получает значение int
!
Кроме того, все функции без возвращаемого типа или типов параметров будут неявно использовать по умолчанию Any
:
def legacy_parser(text):
...
return data
# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
...
return data
Такое поведение позволяет использовать Any
в качестве эскейп-люка, когда вам нужно смешать динамически и статически типизированный код.
Противопоставьте поведение Any
поведению object
. Как и в Any
, каждый тип является подтипом object
. Однако, в отличие от Any
, обратное не верно: object
не является подтипом любого другого типа.
Это означает, что если тип значения object
, программа проверки типов отвергнет почти все операции над ним, а присвоение переменной (или использование ее в качестве возвращаемого значения) более специализированного типа будет ошибкой типа. Например:
def hash_a(item: object) -> int:
# Fails type checking; an object does not have a 'magic' method.
item.magic()
...
def hash_b(item: Any) -> int:
# Passes type checking
item.magic()
...
# Passes type checking, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")
# Passes type checking, since Any is compatible with all types
hash_b(42)
hash_b("foo")
Используйте object
, чтобы указать, что значение может быть любого типа безопасным для типов образом. Используйте Any
, чтобы указать, что значение динамически типизировано.
Номинальная и структурная подтипизация¶
Изначально PEP 484 определил систему статических типов Python как использующую номинальную подтипизацию. Это означает, что класс A
разрешен там, где ожидается класс B
, тогда и только тогда, когда A
является подклассом B
.
Ранее это требование распространялось и на абстрактные базовые классы, такие как Iterable
. Проблема с этим подходом заключалась в том, что класс должен был быть явно помечен для их поддержки, что непитонично и не похоже на то, что обычно делается в идиоматическом динамически типизированном коде Python. Например, это соответствует PEP 484:
from collections.abc import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
PEP 544 позволяет решить эту проблему, позволяя пользователям писать приведенный выше код без явных базовых классов в определении класса, что позволяет Bucket
неявно считаться подтипом и Sized
, и Iterable[int]
при статической проверке типов. Это известно как структурная подтипизация (или статическая утиная подтипизация):
from collections.abc import Iterator, Iterable
class Bucket: # Note: no base classes
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket()) # Passes type check
Более того, подклассифицировав специальный класс Protocol
, пользователь может определить новые пользовательские протоколы, чтобы в полной мере использовать структурную подтипизацию (см. примеры ниже).
Содержание модуля¶
Модуль typing
определяет следующие классы, функции и декораторы.
Специальные примитивы типизации¶
Специальные типы¶
Их можно использовать в качестве типов в аннотациях. Они не поддерживают подписку с использованием []
.
- typing.Any¶
Специальный тип, указывающий на неограниченный тип.
Изменено в версии 3.11:
Any
теперь можно использовать в качестве базового класса. Это может быть полезно для избежания ошибок проверки типов в классах, которые могут «уткать» тип в любом месте или являются очень динамичными.
- typing.AnyStr¶
-
Определение:
AnyStr = TypeVar('AnyStr', str, bytes)
AnyStr
предназначен для функций, которые могут принимать аргументыstr
илиbytes
, но не могут позволить им смешиваться.Например:
def concat(a: AnyStr, b: AnyStr) -> AnyStr: return a + b concat("foo", "bar") # OK, output has type 'str' concat(b"foo", b"bar") # OK, output has type 'bytes' concat("foo", b"bar") # Error, cannot mix str and bytes
Обратите внимание, что, несмотря на свое название,
AnyStr
не имеет ничего общего с типомAny
и не означает «любая строка». В частности,AnyStr
иstr | bytes
отличаются друг от друга и имеют разные случаи использования:# Invalid use of AnyStr: # The type variable is used only once in the function signature, # so cannot be "solved" by the type checker def greet_bad(cond: bool) -> AnyStr: return "hi there!" if cond else b"greetings!" # The better way of annotating this function: def greet_proper(cond: bool) -> str | bytes: return "hi there!" if cond else b"greetings!"
Утратил актуальность с версии 3.13, будет удален в версии 3.18: Утратил актуальность в пользу нового type parameter syntax. Используйте
class A[T: (str, bytes)]: ...
вместо импортаAnyStr
. См. PEP 695 для более подробной информации.В Python 3.16
AnyStr
будет удален изtyping.__all__
, а при обращении кtyping
или его импорте во время выполнения будут выдаваться предупреждения об устаревании. В Python 3.18AnyStr
будет удален изtyping
.
- typing.LiteralString¶
Специальный тип, включающий только литеральные строки.
Любой строковый литерал совместим с
LiteralString
, так же как и другойLiteralString
. Однако объект, типизированный как простоstr
, не совместим. Строка, созданная путем объединения объектов, типизированных какLiteralString
, также допустима какLiteralString
.Пример:
def run_query(sql: LiteralString) -> None: ... def caller(arbitrary_string: str, literal_string: LiteralString) -> None: run_query("SELECT * FROM students") # OK run_query(literal_string) # OK run_query("SELECT * FROM " + literal_string) # OK run_query(arbitrary_string) # type checker error run_query( # type checker error f"SELECT * FROM students WHERE name = {arbitrary_string}" )
LiteralString
полезен для чувствительных API, где произвольные строки, созданные пользователем, могут вызвать проблемы. Например, два вышеприведенных случая, которые генерируют ошибки проверки типов, могут быть уязвимы для атаки SQL-инъекции.Более подробную информацию см. в разделе PEP 675.
Added in version 3.11.
- typing.Never¶
- typing.NoReturn¶
Never
иNoReturn
представляют тип bottom type, у которого нет членов.Они могут использоваться для указания на то, что функция никогда не возвращается, например
sys.exit()
:from typing import Never # or NoReturn def stop() -> Never: raise RuntimeError('no way')
Или определить функцию, которая никогда не должна быть вызвана, поскольку у нее нет допустимых аргументов, например
assert_never()
:from typing import Never # or NoReturn def never_call_me(arg: Never) -> None: pass def int_or_str(arg: int | str) -> None: never_call_me(arg) # type checker error match arg: case int(): print("It's an int") case str(): print("It's a str") case _: never_call_me(arg) # OK, arg is of type Never (or NoReturn)
Never
иNoReturn
имеют одинаковое значение в системе типов, и статические программы проверки типов обрабатывают их эквивалентно.Added in version 3.6.2: Добавлено
NoReturn
.Added in version 3.11: Добавлено
Never
.
- typing.Self¶
Специальный тип для представления текущего вложенного класса.
Например:
from typing import Self, reveal_type class Foo: def return_self(self) -> Self: ... return self class SubclassOfFoo(Foo): pass reveal_type(Foo().return_self()) # Revealed type is "Foo" reveal_type(SubclassOfFoo().return_self()) # Revealed type is "SubclassOfFoo"
Эта аннотация семантически эквивалентна следующей, хотя и более лаконичной:
from typing import TypeVar Self = TypeVar("Self", bound="Foo") class Foo: def return_self(self: Self) -> Self: ... return self
В общем случае, если что-то возвращает
self
, как в приведенных выше примерах, то в качестве аннотации возврата следует использоватьSelf
. Если быFoo.return_self
был аннотирован как возвращающий"Foo"
, то программа проверки типов определила бы, что объект, возвращаемый изSubclassOfFoo.return_self
, имеет типFoo
, а неSubclassOfFoo
.Другие распространенные варианты использования включают:
classmethod
, которые используются как альтернативные конструкторы и возвращают экземпляры параметраcls
.Аннотация метода
__enter__()
, который возвращает self.
Не следует использовать
Self
в качестве аннотации return, если не гарантируется, что метод вернет экземпляр подкласса, когда класс будет подклассифицирован:class Eggs: # Self would be an incorrect return annotation here, # as the object returned is always an instance of Eggs, # even in subclasses def returns_eggs(self) -> "Eggs": return Eggs()
Более подробную информацию см. в разделе PEP 673.
Added in version 3.11.
- typing.TypeAlias¶
Специальная аннотация для явного объявления type alias.
Например:
from typing import TypeAlias Factors: TypeAlias = list[int]
TypeAlias
особенно полезен в старых версиях Python для аннотирования псевдонимов, использующих прямые ссылки, поскольку программам проверки типов бывает сложно отличить их от обычных присваиваний переменных:from typing import Generic, TypeAlias, TypeVar T = TypeVar("T") # "Box" does not exist yet, # so we have to use quotes for the forward reference on Python <3.12. # Using ``TypeAlias`` tells the type checker that this is a type alias declaration, # not a variable assignment to a string. BoxOfStrings: TypeAlias = "Box[str]" class Box(Generic[T]): @classmethod def make_box_of_strings(cls) -> BoxOfStrings: ...
Более подробную информацию см. в разделе PEP 613.
Added in version 3.10.
Не рекомендуется, начиная с версии 3.12: Оператор
TypeAlias
устарел в пользу оператораtype
, который создает экземплярыTypeAliasType
и который изначально поддерживает прямые ссылки. Обратите внимание, что хотя операторыTypeAlias
иTypeAliasType
служат схожим целям и имеют похожие имена, они отличаются друг от друга, и последний не является типом первого. УдалениеTypeAlias
в настоящее время не планируется, но пользователям рекомендуется перейти на операторыtype
.
Специальные формы¶
Их можно использовать в качестве типов в аннотациях. Все они поддерживают подписку с помощью []
, но каждый из них имеет свой уникальный синтаксис.
- typing.Union¶
Союзный тип;
Union[X, Y]
эквивалентенX | Y
и означает либо X, либо Y.Чтобы определить объединение, используйте, например,
Union[int, str]
или сокращениеint | str
. Рекомендуется использовать это сокращение. Подробнее:Аргументы должны быть типами, и их должно быть не менее одного.
Союзы союзов уплощаются, например:
Union[Union[int, str], float] == Union[int, str, float]
Союзы с одним аргументом исчезают, например:
Union[int] == int # The constructor actually returns int
Лишние аргументы пропускаются, например:
Union[int, str, int] == Union[int, str] == int | str
При сравнении союзов порядок аргументов игнорируется, например:
Union[int, str] == Union[str, int]
Вы не можете подклассифицировать или инстанцировать
Union
.Вы не можете написать
Union[X][Y]
.
Изменено в версии 3.7: Не удаляйте явные подклассы из союзов во время выполнения.
Изменено в версии 3.10: Союзы теперь можно записать в виде
X | Y
. См. union type expressions.
- typing.Optional¶
Optional[X]
эквивалентенX | None
(илиUnion[X, None]
).Обратите внимание, что это не то же самое, что понятие необязательного аргумента, который имеет значение по умолчанию. Необязательный аргумент, имеющий значение по умолчанию, не требует наличия квалификатора
Optional
в аннотации типа только потому, что он необязательный. Например:def foo(arg: int = 0) -> None: ...
С другой стороны, если допускается явное значение
None
, уместно использоватьOptional
, независимо от того, является ли аргумент необязательным или нет. Например:def foo(arg: Optional[int] = None) -> None: ...
Изменено в версии 3.10: Теперь опцию можно записать как
X | None
. См. union type expressions.
- typing.Concatenate¶
Специальная форма для аннотирования функций высшего порядка.
Concatenate
может использоваться в сочетании с Callable иParamSpec
для аннотирования вызываемой переменной более высокого порядка, которая добавляет, удаляет или преобразует параметры другой вызываемой переменной. Используется в формеConcatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]
. В настоящее времяConcatenate
действителен только при использовании в качестве первого аргумента Callable. Последний параметрConcatenate
должен бытьParamSpec
или многоточием (...
).Например, для аннотации декоратора
with_lock
, который предоставляетthreading.Lock
декорируемой функции, можно использоватьConcatenate
, чтобы указать, чтоwith_lock
ожидает вызываемую функцию, которая принимаетLock
в качестве первого аргумента, а возвращает вызываемую функцию с другой сигнатурой типа. В этом случаеParamSpec
указывает, что типы параметров возвращаемой вызываемой переменной зависят от типов параметров передаваемой вызываемой переменной:from collections.abc import Callable from threading import Lock from typing import Concatenate # Use this lock to ensure that only one thread is executing a function # at any time. my_lock = Lock() def with_lock[**P, R](f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: '''A type-safe decorator which provides a lock.''' def inner(*args: P.args, **kwargs: P.kwargs) -> R: # Provide the lock as the first argument. return f(my_lock, *args, **kwargs) return inner @with_lock def sum_threadsafe(lock: Lock, numbers: list[float]) -> float: '''Add a list of numbers together in a thread-safe manner.''' with lock: return sum(numbers) # We don't need to pass in the lock ourselves thanks to the decorator. sum_threadsafe([1.1, 2.2, 3.3])
Added in version 3.10.
См.также
PEP 612 – Переменные спецификации параметров (PEP, в котором были представлены
ParamSpec
иConcatenate
)
- typing.Literal¶
Специальная форма типизации для определения «литеральных типов».
Literal
может использоваться для указания программам проверки типов, что аннотированный объект имеет значение, эквивалентное одному из предоставленных литералов.Например:
def validate_simple(data: Any) -> Literal[True]: # always returns True ... type Mode = Literal['r', 'rb', 'w', 'wb'] def open_helper(file: str, mode: Mode) -> str: ... open_helper('/some/path', 'r') # Passes type check open_helper('/other/path', 'typo') # Error in type checker
Literal[...]
не может быть подклассом. Во время выполнения в качестве аргумента типа дляLiteral[...]
допускается произвольное значение, но программы проверки типов могут накладывать ограничения. Более подробную информацию о литеральных типах см. в разделе PEP 586.Added in version 3.8.
- typing.ClassVar¶
Специальная конструкция типа для обозначения переменных класса.
Как было введено в PEP 526, аннотация переменной, обернутая в ClassVar, указывает, что данный атрибут предназначен для использования в качестве переменной класса и не должен устанавливаться для экземпляров этого класса. Использование:
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variable
ClassVar
принимает только типы и не может быть дополнительно подписан.ClassVar
сам по себе не является классом и не должен использоваться сisinstance()
илиissubclass()
.ClassVar
не изменяет поведение Python во время выполнения, но может использоваться сторонними программами проверки типов. Например, программа проверки типов может отметить следующий код как ошибку:enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OK
Added in version 3.5.3.
- typing.Final¶
Специальная конструкция типизации для указания конечных имен программам проверки типов.
Конечные имена не могут быть переназначены в любой области видимости. Конечные имена, объявленные в областях видимости класса, не могут быть переопределены в подклассах.
Например:
MAX_SIZE: Final = 9000 MAX_SIZE += 1 # Error reported by type checker class Connection: TIMEOUT: Final[int] = 10 class FastConnector(Connection): TIMEOUT = 1 # Error reported by type checker
Проверка этих свойств во время выполнения не производится. Более подробную информацию см. в разделе PEP 591.
Added in version 3.8.
- typing.Required¶
Специальная конструкция для обозначения клавиши
TypedDict
как необходимой.В основном это полезно для
total=False
TypedDicts. Более подробную информацию см. вTypedDict
и PEP 655.Added in version 3.11.
- typing.NotRequired¶
Специальная конструкция для пометки клавиши
TypedDict
как потенциально отсутствующей.Более подробную информацию см. в разделах
TypedDict
и PEP 655.Added in version 3.11.
- typing.ReadOnly¶
Специальная конструкция типизации, позволяющая пометить элемент
TypedDict
как доступный только для чтения.Например:
class Movie(TypedDict): title: ReadOnly[str] year: int def mutate_movie(m: Movie) -> None: m["year"] = 1992 # allowed m["title"] = "The Matrix" # typechecker error
Это свойство не проверяется во время выполнения.
Более подробную информацию см. в разделах
TypedDict
и PEP 705.Added in version 3.13.
- typing.Annotated¶
Специальная форма набора для добавления контекстно-зависимых метаданных к аннотации.
Добавьте метаданные
x
к заданному типуT
с помощью аннотацииAnnotated[T, x]
. Метаданные, добавленные с помощьюAnnotated
, могут быть использованы инструментами статического анализа или во время выполнения. Во время выполнения метаданные хранятся в атрибуте__metadata__
.Если библиотека или инструмент встречает аннотацию
Annotated[T, x]
и не имеет специальной логики для метаданных, она должна игнорировать метаданные и просто рассматривать аннотацию какT
. Таким образом,Annotated
может быть полезен для кода, который хочет использовать аннотации для целей, выходящих за рамки статической системы типизации Python.Использование
Annotated[T, x]
в качестве аннотации по-прежнему позволяет осуществлять статическую проверку типов дляT
, так как программы проверки типов будут просто игнорировать метаданныеx
. ЭтимAnnotated
отличается от декоратора@no_type_check
, который также может быть использован для добавления аннотаций вне области действия системы типизации, но полностью отключает проверку типов для функции или класса.Ответственность за интерпретацию метаданных лежит на инструменте или библиотеке, столкнувшейся с аннотацией
Annotated
. Инструмент или библиотека, столкнувшиеся с типомAnnotated
, могут просмотреть элементы метаданных, чтобы определить, представляют ли они интерес (например, используяisinstance()
).- Annotated[<type>, <metadata>]
Вот пример того, как можно использовать
Annotated
для добавления метаданных к аннотациям типов, если вы проводите анализ диапазона:@dataclass class ValueRange: lo: int hi: int T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)]
Детали синтаксиса:
Первый аргумент
Annotated
должен быть допустимого типаМожно предоставить несколько элементов метаданных (
Annotated
поддерживает переменные аргументы):@dataclass class ctype: kind: str Annotated[int, ValueRange(3, 10), ctype("char")]
Решение о том, разрешено ли клиенту добавлять несколько элементов метаданных в одну аннотацию и как объединять эти аннотации, принимает инструмент, потребляющий аннотации.
Annotated
должен быть подзаписан не менее чем двумя аргументами (Annotated[int]
недопустим)Порядок элементов метаданных сохраняется и имеет значение для проверки равенства:
assert Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[ int, ctype("char"), ValueRange(3, 10) ]
Вложенные типы
Annotated
сглаживаются. Порядок элементов метаданных начинается с самой внутренней аннотации:assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ]
Дублирующиеся элементы метаданных не удаляются:
assert Annotated[int, ValueRange(3, 10)] != Annotated[ int, ValueRange(3, 10), ValueRange(3, 10) ]
Annotated
можно использовать с вложенными и общими псевдонимами:@dataclass class MaxLen: value: int type Vec[T] = Annotated[list[tuple[T, T]], MaxLen(10)] # When used in a type annotation, a type checker will treat "V" the same as # ``Annotated[list[tuple[int, int]], MaxLen(10)]``: type V = Vec[int]
Annotated
нельзя использовать с распакованнымTypeVarTuple
:type Variadic[*Ts] = Annotated[*Ts, Ann1] # NOT valid
Это эквивалентно:
Annotated[T1, T2, T3, ..., Ann1]
где
T1
,T2
и т. д. являютсяTypeVars
. Это будет неверно: в Annotated должен передаваться только один тип.По умолчанию
get_type_hints()
удаляет метаданные из аннотаций. Передайтеinclude_extras=True
, чтобы метаданные были сохранены:>>> from typing import Annotated, get_type_hints >>> def func(x: Annotated[int, "metadata"]) -> None: pass ... >>> get_type_hints(func) {'x': <class 'int'>, 'return': <class 'NoneType'>} >>> get_type_hints(func, include_extras=True) {'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>}
Во время выполнения метаданные, связанные с типом
Annotated
, могут быть получены с помощью атрибута__metadata__
:>>> from typing import Annotated >>> X = Annotated[int, "very", "important", "metadata"] >>> X typing.Annotated[int, 'very', 'important', 'metadata'] >>> X.__metadata__ ('very', 'important', 'metadata')
См.также
- PEP 593 - Гибкие аннотации функций и переменных
PEP, вводящий
Annotated
в стандартную библиотеку.
Added in version 3.9.
- typing.TypeIs¶
Специальная конструкция типизации для обозначения предикатных функций пользовательского типа.
TypeIs
может использоваться для аннотирования возвращаемого типа функции предиката типа, определяемого пользователем.TypeIs
принимает только один аргумент типа. Во время выполнения функции, помеченные таким образом, должны возвращать булево значение и принимать по крайней мере один позиционный аргумент.TypeIs
нацелен на извлечение пользы из сужения типа - техники, используемой статическими программами проверки типов для определения более точного типа выражения в потоке кода программы. Обычно сужение типа выполняется путем анализа условного потока кода и применения сужения к блоку кода. Условное выражение здесь иногда называют «предикатом типа»:def is_str(val: str | float): # "isinstance" type predicate if isinstance(val, str): # Type of ``val`` is narrowed to ``str`` ... else: # Else, type of ``val`` is narrowed to ``float``. ...
Иногда в качестве предиката типа удобно использовать определяемую пользователем булеву функцию. Такая функция должна использовать
TypeIs[...]
илиTypeGuard
в качестве возвращаемого типа, чтобы предупредить статические средства проверки типов о таком намерении.TypeIs
обычно имеет более интуитивное поведение, чемTypeGuard
, но его нельзя использовать, когда входной и выходной типы несовместимы (например,list[object]
-list[int]
) или когда функция не возвращаетTrue
для всех экземпляров суженного типа.Использование
-> TypeIs[NarrowedType]
сообщает программе статической проверки типов, что для данной функции:Возвращаемое значение - булево.
Если возвращаемое значение равно
True
, то тип его аргумента равен пересечению исходного типа аргумента иNarrowedType
.Если возвращаемое значение равно
False
, тип его аргумента сужается, чтобы исключитьNarrowedType
.
Например:
from typing import assert_type, final, TypeIs class Parent: pass class Child(Parent): pass @final class Unrelated: pass def is_parent(val: object) -> TypeIs[Parent]: return isinstance(val, Parent) def run(arg: Child | Unrelated): if is_parent(arg): # Type of ``arg`` is narrowed to the intersection # of ``Parent`` and ``Child``, which is equivalent to # ``Child``. assert_type(arg, Child) else: # Type of ``arg`` is narrowed to exclude ``Parent``, # so only ``Unrelated`` is left. assert_type(arg, Unrelated)
Тип внутри
TypeIs
должен соответствовать типу аргумента функции; если это не так, статические программы проверки типов выдадут ошибку. Неправильно написанная функцияTypeIs
может привести к некорректному поведению системы типов; пользователь обязан писать такие функции безопасным для типов образом.Если функция
TypeIs
является методом класса или экземпляра, то тип вTypeIs
отображается на тип второго параметра послеcls
илиself
.Короче говоря, форма
def foo(arg: TypeA) -> TypeIs[TypeB]: ...
означает, что еслиfoo(arg)
возвращаетTrue
, тоarg
является экземпляромTypeB
, а если возвращаетFalse
, то не является экземпляромTypeB
.TypeIs
также работает с переменными типа. Дополнительные сведения см. в разделе PEP 742 (Сужение типов с помощьюTypeIs
).Added in version 3.13.
- typing.TypeGuard¶
Специальная конструкция типизации для обозначения предикатных функций пользовательского типа.
Функции предиката типа - это определяемые пользователем функции, которые возвращают, является ли их аргумент экземпляром определенного типа.
TypeGuard
работает так же, как иTypeIs
, но оказывает несколько иное влияние на поведение проверки типов (см. ниже).Использование
-> TypeGuard
сообщает программе статической проверки типов, что для данной функции:Возвращаемое значение - булево.
Если возвращаемое значение равно
True
, то тип его аргумента - это тип внутриTypeGuard
.
TypeGuard
также работает с переменными типа. Более подробную информацию см. в разделе PEP 647.Например:
def is_str_list(val: list[object]) -> TypeGuard[list[str]]: '''Determines whether all objects in the list are strings''' return all(isinstance(x, str) for x in val) def func1(val: list[object]): if is_str_list(val): # Type of ``val`` is narrowed to ``list[str]``. print(" ".join(val)) else: # Type of ``val`` remains as ``list[object]``. print("Not a list of strings!")
TypeIs
иTypeGuard
различаются следующим образом:TypeIs
требует, чтобы суженный тип был подтипом входного типа, аTypeGuard
- нет. Основная причина - возможность суженияlist[object]
доlist[str]
, даже если последний не является подтипом первого, посколькуlist
инвариантен.Когда функция
TypeGuard
возвращаетTrue
, средства проверки типов сужают тип переменной до точного типаTypeGuard
. Когда функцияTypeIs
возвращаетTrue
, средства проверки типов могут вывести более точный тип, объединив ранее известный тип переменной с типомTypeIs
. (Технически это называется типом пересечения).Когда функция
TypeGuard
возвращаетFalse
, средства проверки типов не могут сузить тип переменной. Когда функцияTypeIs
возвращаетFalse
, средства проверки типов могут сузить тип переменной, чтобы исключить типTypeIs
.
Added in version 3.10.
- typing.Unpack¶
Оператор типизации для концептуального обозначения объекта как распакованного.
Например, использование оператора распаковки
*
на type variable tuple эквивалентно использованиюUnpack
, чтобы пометить кортеж переменных типа как распакованный:Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Effectively does: tup: tuple[Unpack[Ts]]
На самом деле,
Unpack
может использоваться как взаимозаменяемый с*
в контексте типовtyping.TypeVarTuple
иbuiltins.tuple
. Вы можете встретить явное использованиеUnpack
в старых версиях Python, где*
нельзя было использовать в некоторых местах:# In older versions of Python, TypeVarTuple and Unpack # are located in the `typing_extensions` backports package. from typing_extensions import TypeVarTuple, Unpack Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Syntax error on Python <= 3.10! tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible
Unpack
также может использоваться вместе сtyping.TypedDict
для ввода**kwargs
в сигнатуре функции:from typing import TypedDict, Unpack class Movie(TypedDict): name: str year: int # This function expects two keyword arguments - `name` of type `str` # and `year` of type `int`. def foo(**kwargs: Unpack[Movie]): ...
Подробнее об использовании
Unpack
для набора**kwargs
см. в разделе PEP 692.Added in version 3.11.
Создание общих типов и псевдонимов типов¶
Следующие классы не должны использоваться непосредственно в качестве аннотаций. Их предназначение - быть строительными блоками для создания общих типов и псевдонимов типов.
Эти объекты могут быть созданы с помощью специального синтаксиса (оператор:ref:type parameter lists <type-params> и оператор type
). Для совместимости с Python 3.11 и более ранними версиями они также могут быть созданы без специального синтаксиса, как описано ниже.
- class typing.Generic¶
Абстрактный базовый класс для общих типов.
Родовой тип обычно объявляется путем добавления списка параметров типа после имени класса:
class Mapping[KT, VT]: def __getitem__(self, key: KT) -> VT: ... # Etc.
Такой класс неявно наследуется от
Generic
. Семантика этого синтаксиса во время выполнения обсуждается в Language Reference.Этот класс можно использовать следующим образом:
def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return default
Здесь скобки после имени функции обозначают generic function.
Для обратной совместимости общие классы также могут быть объявлены путем явного наследования от
Generic
. В этом случае параметры типа должны быть объявлены отдельно:KT = TypeVar('KT') VT = TypeVar('VT') class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
- class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)¶
Тип переменный.
Предпочтительным способом создания переменной типа является специальный синтаксис для generic functions, generic classes и generic type aliases:
class Sequence[T]: # T is a TypeVar ...
Этот синтаксис также можно использовать для создания связанных и ограниченных переменных типа:
class StrSequence[S: str]: # S is a TypeVar bound to str ... class StrOrBytesSequence[A: (str, bytes)]: # A is a TypeVar constrained to str or bytes ...
Однако при желании многоразовые переменные типа можно сконструировать и вручную, например, так:
T = TypeVar('T') # Can be anything S = TypeVar('S', bound=str) # Can be any subtype of str A = TypeVar('A', str, bytes) # Must be exactly str or bytes
Переменные типа существуют в первую очередь для статической проверки типов. Они служат параметрами для родовых типов, а также для определения родовых функций и псевдонимов типов. Более подробную информацию о родовых типах смотрите в
Generic
. Родовые функции работают следующим образом:def repeat[T](x: T, n: int) -> Sequence[T]: """Return a list containing n references to x.""" return [x]*n def print_capitalized[S: str](x: S) -> S: """Print x capitalized, and return x.""" print(x.capitalize()) return x def concatenate[A: (str, bytes)](x: A, y: A) -> A: """Add two strings or bytes objects together.""" return x + y
Обратите внимание, что переменные типа могут быть связанными, ограниченными или ни теми, ни другими, но не могут быть одновременно связанными и ограниченными.
Инвариантность переменных типа определяется программами проверки типов при их создании с помощью type parameter syntax или при передаче
infer_variance=True
. Переменные типа, созданные вручную, могут быть явно помечены как ковариантные или контравариантные путем передачиcovariant=True
илиcontravariant=True
. По умолчанию переменные типа, созданные вручную, являются инвариантными. Более подробную информацию см. в PEP 484 и PEP 695.Переменные связанного типа и переменные ограниченного типа имеют разную семантику в нескольких важных аспектах. Использование связанной переменной типа означает, что для решения
TypeVar
будет использован самый конкретный тип из возможных:x = print_capitalized('a string') reveal_type(x) # revealed type is str class StringSubclass(str): pass y = print_capitalized(StringSubclass('another string')) reveal_type(y) # revealed type is StringSubclass z = print_capitalized(45) # error: int is not a subtype of str
Переменные типа могут быть связаны с конкретными типами, абстрактными типами (ABC или протоколами) и даже с объединениями типов:
# Can be anything with an __abs__ method def print_abs[T: SupportsAbs](arg: T) -> None: print("Absolute value:", abs(arg)) U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
Использование переменной ограниченного типа, однако, означает, что
TypeVar
может быть решен только как один из заданных ограничений:a = concatenate('one', 'two') reveal_type(a) # revealed type is str b = concatenate(StringSubclass('one'), StringSubclass('two')) reveal_type(b) # revealed type is str, despite StringSubclass being passed in c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not both
Во время выполнения
isinstance(x, T)
подниметTypeError
.- __name__¶
Имя переменной типа.
- __covariant__¶
Был ли тип var явно помечен как ковариантный.
- __contravariant__¶
Был ли тип var явно помечен как контравариантный.
- __infer_variance__¶
Должна ли дисперсия переменной типа выводиться средствами проверки типов.
Added in version 3.12.
- __bound__¶
Граница переменной типа, если таковая имеется.
Изменено в версии 3.12: Для переменных типа, созданных с помощью type parameter syntax, привязка оценивается только при обращении к атрибуту, а не при создании переменной типа (см. Ленивая оценка).
- __constraints__¶
Кортеж, содержащий ограничения переменной типа, если таковые имеются.
Изменено в версии 3.12: Для переменных типа, созданных с помощью type parameter syntax, ограничения оцениваются только при обращении к атрибуту, а не при создании переменной типа (см. Ленивая оценка).
- __default__¶
Значение по умолчанию переменной типа, или
typing.NoDefault
, если она не имеет значения по умолчанию.Added in version 3.13.
- has_default()¶
Возвращает, имеет ли переменная типа значение по умолчанию. Это эквивалентно проверке того, не является ли
__default__
синглтономtyping.NoDefault
, за исключением того, что это не заставляет оценивать значение по умолчанию lazily evaluated.Added in version 3.13.
Изменено в версии 3.12: Переменные типа теперь можно объявлять, используя синтаксис type parameter, введенный в PEP 695. Был добавлен параметр
infer_variance
.Изменено в версии 3.13: Добавлена поддержка значений по умолчанию.
- class typing.TypeVarTuple(name, *, default=typing.NoDefault)¶
Кортеж переменных типа. Специализированная форма type variable, позволяющая использовать вариативные дженерики.
Кортежи переменных типа могут быть объявлены в формате type parameter lists с использованием одной звездочки (
*
) перед именем:def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])
Или явно вызвав конструктор
TypeVarTuple
:T = TypeVar("T") Ts = TypeVarTuple("Ts") def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])
Обычная переменная типа позволяет параметризовать один тип. Кортеж переменной типа, напротив, позволяет параметризовать произвольное количество типов, действуя как произвольное количество переменных типа, обернутых в кортеж. Например:
# T is bound to int, Ts is bound to () # Return value is (1,), which has type tuple[int] move_first_element_to_last(tup=(1,)) # T is bound to int, Ts is bound to (str,) # Return value is ('spam', 1), which has type tuple[str, int] move_first_element_to_last(tup=(1, 'spam')) # T is bound to int, Ts is bound to (str, float) # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int] move_first_element_to_last(tup=(1, 'spam', 3.0)) # This fails to type check (and fails at runtime) # because tuple[()] is not compatible with tuple[T, *Ts] # (at least one element is required) move_first_element_to_last(tup=())
Обратите внимание на использование оператора распаковки
*
вtuple[T, *Ts]
. Концептуально, вы можете представитьTs
как кортеж переменных типа(T1, T2, ...)
. Тогдаtuple[T, *Ts]
станетtuple[T, *(T1, T2, ...)]
, что эквивалентноtuple[T, T1, T2, ...]
. (Обратите внимание, что в старых версиях Python вместоUnpack
можно увидетьUnpack[Ts]
).Кортежи переменных типов должны всегда быть распакованы. Это помогает отличить кортежи переменных типа от обычных переменных типа:
x: Ts # Not valid x: tuple[Ts] # Not valid x: tuple[*Ts] # The correct way to do it
Кортежи переменных типа могут использоваться в тех же контекстах, что и обычные переменные типа. Например, в определениях классов, аргументов и возвращаемых типов:
class Array[*Shape]: def __getitem__(self, key: tuple[*Shape]) -> float: ... def __abs__(self) -> "Array[*Shape]": ... def get_shape(self) -> tuple[*Shape]: ...
Кортежи переменных типов можно удачно комбинировать с обычными переменными типов:
class Array[DType, *Shape]: # This is fine pass class Array2[*Shape, DType]: # This would also be fine pass class Height: ... class Width: ... float_array_1d: Array[float, Height] = Array() # Totally fine int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
Однако обратите внимание, что в одном списке аргументов типа или параметров типа может присутствовать не более одного кортежа переменных типа:
x: tuple[*Ts, *Ts] # Not valid class Array[*Shape, *Shape]: # Not valid pass
Наконец, в качестве аннотации типа
*args
можно использовать распакованный кортеж переменных типа:def call_soon[*Ts]( callback: Callable[[*Ts], None], *args: *Ts ) -> None: ... callback(*args)
В отличие от нераспакованных аннотаций
*args
- например,*args: int
, которые указывают, что все аргументы являютсяint
. -*args: *Ts
позволяет ссылаться на типы отдельных аргументов в*args
. Здесь это позволяет нам убедиться, что типы*args
, переданных вcall_soon
, соответствуют типам (позиционных) аргументовcallback
.Более подробную информацию о кортежах переменных типов см. в разделе PEP 646.
- __name__¶
Имя кортежа переменных типа.
- __default__¶
Значение по умолчанию для кортежа переменных типа, или
typing.NoDefault
, если значение по умолчанию отсутствует.Added in version 3.13.
- has_default()¶
Возвращает, имеет ли кортеж переменных типа значение по умолчанию. Это эквивалентно проверке того, не является ли
__default__
синглетономtyping.NoDefault
, за исключением того, что это не заставляет оценивать значение по умолчанию lazily evaluated.Added in version 3.13.
Added in version 3.11.
Изменено в версии 3.12: Кортежи переменных типа теперь можно объявлять, используя синтаксис type parameter, введенный в PEP 695.
Изменено в версии 3.13: Добавлена поддержка значений по умолчанию.
- class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault)¶
Переменная спецификации параметра. Специализированная версия type variables.
В type parameter lists спецификации параметров могут быть объявлены с помощью двух звездочек (
**
):type IntFunc[**P] = Callable[P, int]
Для совместимости с Python 3.11 и более ранними версиями объекты
ParamSpec
также могут быть созданы следующим образом:P = ParamSpec('P')
Переменные спецификации параметров существуют в первую очередь для удобства статической проверки типов. Они используются для передачи типов параметров одного вызываемого объекта другому вызываемому объекту - шаблон, часто встречающийся в функциях более высокого порядка и декораторах. Они действительны только при использовании в
Concatenate
, или в качестве первого аргументаCallable
, или в качестве параметров для пользовательских Generics. Дополнительную информацию о родовых типах см. вGeneric
.Например, чтобы добавить базовое протоколирование в функцию, можно создать декоратор
add_logging
для протоколирования вызовов функции. Переменная спецификации параметров сообщает программе проверки типов, что вызываемая переменная, переданная в декоратор, и возвращаемая им новая вызываемая переменная имеют взаимозависимые параметры типа:from collections.abc import Callable import logging def add_logging[T, **P](f: Callable[P, T]) -> Callable[P, T]: '''A type-safe decorator to add logging to a function.''' def inner(*args: P.args, **kwargs: P.kwargs) -> T: logging.info(f'{f.__name__} was called') return f(*args, **kwargs) return inner @add_logging def add_two(x: float, y: float) -> float: '''Add two numbers together.''' return x + y
При отсутствии
ParamSpec
самым простым способом аннотирования было использованиеTypeVar
с привязкойCallable[..., Any]
. Однако это приводит к двум проблемам:Программа проверки типов не может проверить функцию
inner
, потому что*args
и**kwargs
должны быть типизированыAny
.cast()
может потребоваться в теле декоратораadd_logging
при возврате функцииinner
, либо статической проверке типов нужно указать игнорироватьreturn inner
.
- args¶
- kwargs¶
Поскольку
ParamSpec
охватывает как позиционные, так и ключевые параметры,P.args
иP.kwargs
можно использовать для разделенияParamSpec
на составляющие.P.args
представляет собой кортеж позиционных параметров в данном вызове и должен использоваться только для аннотирования*args
.P.kwargs
представляет собой отображение параметров ключевых слов на их значения в данном вызове и должен использоваться только для аннотирования**kwargs
. Оба атрибута требуют, чтобы аннотируемый параметр находился в области видимости. Во время выполненияP.args
иP.kwargs
являются экземплярамиParamSpecArgs
иParamSpecKwargs
соответственно.
- __name__¶
Имя спецификации параметра.
- __default__¶
Значение по умолчанию для спецификации параметра, или
typing.NoDefault
, если значение по умолчанию отсутствует.Added in version 3.13.
- has_default()¶
Возвращает, имеет ли спецификация параметра значение по умолчанию. Это эквивалентно проверке того, не является ли
__default__
синглетономtyping.NoDefault
, за исключением того, что это не заставляет оценивать значение по умолчанию lazily evaluated.Added in version 3.13.
Переменные спецификации параметров, созданные с помощью
covariant=True
илиcontravariant=True
, могут быть использованы для объявления ковариантных или контравариантных общих типов. Аргументbound
также принимается, как иTypeVar
. Однако реальная семантика этих ключевых слов еще не определена.Added in version 3.10.
Изменено в версии 3.12: Спецификации параметров теперь можно объявлять, используя синтаксис type parameter, введенный в PEP 695.
Изменено в версии 3.13: Добавлена поддержка значений по умолчанию.
Примечание
Мариновать можно только переменные спецификации параметров, определенные в глобальной области видимости.
См.также
PEP 612 – Переменные спецификации параметров (PEP, в котором были представлены
ParamSpec
иConcatenate
)
- typing.ParamSpecArgs¶
- typing.ParamSpecKwargs¶
Аргументы и ключевые слова аргументов являются атрибутами
ParamSpec
. АтрибутP.args
атрибутаParamSpec
является экземпляромParamSpecArgs
, аP.kwargs
- экземпляромParamSpecKwargs
. Они предназначены для интроспекции во время выполнения и не имеют особого значения для статических средств проверки типов.Вызов
get_origin()
на любом из этих объектов вернет исходныйParamSpec
:>>> from typing import ParamSpec, get_origin >>> P = ParamSpec("P") >>> get_origin(P.args) is P True >>> get_origin(P.kwargs) is P True
Added in version 3.10.
- class typing.TypeAliasType(name, value, *, type_params=())¶
Тип псевдонимов типов, созданных с помощью оператора
type
.Пример:
>>> type Alias = int >>> type(Alias) <class 'typing.TypeAliasType'>
Added in version 3.12.
- __name__¶
Имя псевдонима типа:
>>> type Alias = int >>> Alias.__name__ 'Alias'
- __module__¶
Модуль, в котором был определен псевдоним типа:
>>> type Alias = int >>> Alias.__module__ '__main__'
- __type_params__¶
Параметры типа псевдонима типа, или пустой кортеж, если псевдоним не является общим:
>>> type ListOrSet[T] = list[T] | set[T] >>> ListOrSet.__type_params__ (T,) >>> type NotGeneric = int >>> NotGeneric.__type_params__ ()
- __value__¶
Значение псевдонима типа. Это значение lazily evaluated, поэтому имена, используемые в определении псевдонима, не будут разрешены до тех пор, пока не будет получен доступ к атрибуту
__value__
:>>> type Mutually = Recursive >>> type Recursive = Mutually >>> Mutually Mutually >>> Recursive Recursive >>> Mutually.__value__ Recursive >>> Recursive.__value__ Mutually
Другие специальные директивы¶
Эти функции и классы не должны использоваться непосредственно в качестве аннотаций. Их предназначение - быть строительными блоками для создания и объявления типов.
- class typing.NamedTuple¶
Типизированная версия
collections.namedtuple()
.Использование:
class Employee(NamedTuple): name: str id: int
Это эквивалентно:
Employee = collections.namedtuple('Employee', ['name', 'id'])
Чтобы придать полю значение по умолчанию, вы можете присвоить ему в теле класса:
class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3
Поля со значением по умолчанию должны располагаться после полей без значения по умолчанию.
Полученный класс имеет дополнительный атрибут
__annotations__
, содержащий дикту, которая сопоставляет имена полей с их типами. (Имена полей находятся в атрибуте_fields
, а значения по умолчанию - в атрибуте_field_defaults
, оба из которых являются частьюnamedtuple()
. API.)NamedTuple
У подклассов также могут быть документы и методы:class Employee(NamedTuple): """Represents an employee.""" name: str id: int = 3 def __repr__(self) -> str: return f'<Employee {self.name}, id={self.id}>'
NamedTuple
подклассы могут быть общими:class Group[T](NamedTuple): key: T group: list[T]
Использование с обратной совместимостью:
# For creating a generic NamedTuple on Python 3.11 or lower class Group(NamedTuple, Generic[T]): key: T group: list[T] # A functional syntax is also supported Employee = NamedTuple('Employee', [('name', str), ('id', int)])
Изменено в версии 3.6: Добавлена поддержка синтаксиса аннотации переменных PEP 526.
Изменено в версии 3.6.1: Добавлена поддержка значений по умолчанию, методов и документальных строк.
Изменено в версии 3.8: Атрибуты
_field_types
и__annotations__
теперь являются обычными словарями, а не экземплярамиOrderedDict
.Изменено в версии 3.9: Удален атрибут
_field_types
в пользу более стандартного атрибута__annotations__
, который содержит ту же информацию.Изменено в версии 3.11: Добавлена поддержка общих именованных кортежей.
Утратил актуальность с версии 3.13, будет удален в версии 3.15: Недокументированный синтаксис аргумента ключевого слова для создания классов NamedTuple (
NT = NamedTuple("NT", x=int)
) является устаревшим и будет запрещен в версии 3.15. Вместо этого используйте синтаксис, основанный на классах, или функциональный синтаксис.Утратил актуальность с версии 3.13, будет удален в версии 3.15: При использовании функционального синтаксиса для создания класса NamedTuple непередача значения параметру „fields“ (
NT = NamedTuple("NT")
) является устаревшей. ПередачаNone
в параметр „fields“ (NT = NamedTuple("NT", None)
) также является устаревшей. Оба параметра будут запрещены в Python 3.15. Чтобы создать класс NamedTuple с 0 полями, используйтеclass NT(NamedTuple): pass
илиNT = NamedTuple("NT", [])
.
- class typing.NewType(name, tp)¶
Класс-помощник для создания низкозатратных distinct types.
Проверка типов считает
NewType
отдельным типом. Однако во время выполнения вызовNewType
возвращает его аргумент без изменений.Использование:
UserId = NewType('UserId', int) # Declare the NewType "UserId" first_user = UserId(1) # "UserId" returns the argument unchanged at runtime
- __module__¶
Модуль, в котором определен новый тип.
- __name__¶
Имя нового типа.
- __supertype__¶
Тип, на котором основан новый тип.
Added in version 3.5.2.
Изменено в версии 3.10:
NewType
теперь является классом, а не функцией.
- class typing.Protocol(Generic)¶
Базовый класс для классов протоколов.
Классы протоколов определяются следующим образом:
class Proto(Protocol): def meth(self) -> int: ...
Такие классы в основном используются в статических программах проверки типов, которые распознают структурную подтипизацию (статическая утиная типизация), например:
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
Более подробную информацию см. в разделе PEP 544. Классы протоколов, украшенные
runtime_checkable()
(описанные позже), действуют как простые протоколы времени выполнения, которые проверяют только наличие заданных атрибутов, игнорируя их сигнатуры типов.Классы протоколов могут быть общими, например:
class GenProto[T](Protocol): def meth(self) -> T: ...
В коде, который должен быть совместим с Python 3.11 или старше, общие протоколы могут быть написаны следующим образом:
T = TypeVar("T") class GenProto(Protocol[T]): def meth(self) -> T: ...
Added in version 3.8.
- @typing.runtime_checkable¶
Пометить класс протокола как протокол времени выполнения.
Такой протокол можно использовать с
isinstance()
иissubclass()
. Это поднимаетTypeError
, когда применяется к классу без протокола. Это позволяет выполнить простую структурную проверку, очень похожую на «одноруких пони» вcollections.abc
, таких какIterable
. Например:@runtime_checkable class Closable(Protocol): def close(self): ... assert isinstance(open('/some/file'), Closable) @runtime_checkable class Named(Protocol): name: str import threading assert isinstance(threading.Thread(name='Bob'), Named)
Примечание
runtime_checkable()
будет проверять только наличие требуемых методов или атрибутов, но не их сигнатуры или типы. Например,ssl.SSLObject
- это класс, поэтому он проходит проверкуissubclass()
против Callable. Однако методssl.SSLObject.__init__
существует только для того, чтобы вызватьTypeError
с более информативным сообщением, что делает невозможным вызов (инстанцирование)ssl.SSLObject
.Примечание
Проверка
isinstance()
на протокол, проверяемый во время выполнения, может быть удивительно медленной по сравнению с проверкойisinstance()
на непротокольный класс. Рассмотрите возможность использования альтернативных идиом, таких как вызовыhasattr()
, для структурных проверок в коде, чувствительном к производительности.Added in version 3.8.
Изменено в версии 3.12: Внутренняя реализация проверки
isinstance()
на соответствие протоколам, проверяемым временем выполнения, теперь используетinspect.getattr_static()
для поиска атрибутов (ранее использовалсяhasattr()
). В результате некоторые объекты, которые раньше считались экземплярами протокола, проверяемого временем выполнения, могут больше не считаться экземплярами этого протокола на Python 3.12+, и наоборот. Большинство пользователей вряд ли пострадают от этого изменения.Изменено в версии 3.12: Члены протокола, проверяемого временем выполнения, теперь считаются «замороженными» во время выполнения, как только класс был создан. Подстановка атрибутов в протокол, проверяемый во время выполнения, по-прежнему будет работать, но не будет влиять на проверки
isinstance()
, сравнивающие объекты с протоколом. Более подробную информацию см. в разделе «What’s new in Python 3.12».
- class typing.TypedDict(dict)¶
Специальная конструкция для добавления подсказок типа в словарь. Во время выполнения это обычное
dict
.TypedDict
объявляет тип словаря, который ожидает, что все его экземпляры будут иметь определенный набор ключей, где каждый ключ связан со значением последовательного типа. Это ожидание не проверяется во время выполнения, а только принудительно выполняется программами проверки типов. Использование:class Point2D(TypedDict): x: int y: int label: str a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
Альтернативным способом создания
TypedDict
является использование синтаксиса вызова функции. Второй аргумент должен быть литераломdict
:Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
Этот функциональный синтаксис позволяет определять ключи, которые не являются действительными identifiers, например, потому что они являются ключевыми словами или содержат дефисы:
# raises SyntaxError class Point2D(TypedDict): in: int # 'in' is a keyword x-y: int # name with hyphens # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
По умолчанию все ключи должны присутствовать в
TypedDict
. Можно пометить отдельные ключи как необязательные с помощьюNotRequired
:class Point2D(TypedDict): x: int y: int label: NotRequired[str] # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})
Это означает, что для
Point2D
TypedDict
может быть опущен ключlabel
.Также можно пометить все ключи как необязательные по умолчанию, указав совокупность
False
:class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)
Это означает, что в
Point2D
TypedDict
может быть опущен любой из ключей. Предполагается, что программа проверки типов будет поддерживать только литералFalse
илиTrue
в качестве значения аргументаtotal
.True
используется по умолчанию и делает обязательными все элементы, определенные в теле класса.Отдельные клавиши
total=False
TypedDict
могут быть отмечены по мере необходимости с помощьюRequired
:class Point2D(TypedDict, total=False): x: Required[int] y: Required[int] label: str # Alternative syntax Point2D = TypedDict('Point2D', { 'x': Required[int], 'y': Required[int], 'label': str }, total=False)
Тип
TypedDict
может наследоваться от одного или нескольких других типовTypedDict
, используя синтаксис, основанный на классах. Использование:class Point3D(Point2D): z: int
В
Point3D
есть три элемента:x
,y
иz
. Это определение эквивалентно следующему:class Point3D(TypedDict): x: int y: int z: int
Класс
TypedDict
не может наследоваться от класса неTypedDict
, за исключениемGeneric
. Например:class X(TypedDict): x: int class Y(TypedDict): y: int class Z(object): pass # A non-TypedDict class class XY(X, Y): pass # OK class XZ(X, Z): pass # raises TypeError
Значение
TypedDict
может быть общим:class Group[T](TypedDict): key: T group: list[T]
Чтобы создать общий
TypedDict
, совместимый с Python 3.11 или ниже, явно наследуйте отGeneric
:T = TypeVar("T") class Group(TypedDict, Generic[T]): key: T group: list[T]
В
TypedDict
можно интроспектировать с помощью dicts аннотаций (см. Лучшие практики использования аннотаций для получения дополнительной информации о лучших практиках аннотаций),__total__
,__required_keys__
и__optional_keys__
.- __total__¶
Point2D.__total__
дает значение аргументаtotal
. Пример:>>> from typing import TypedDict >>> class Point2D(TypedDict): pass >>> Point2D.__total__ True >>> class Point2D(TypedDict, total=False): pass >>> Point2D.__total__ False >>> class Point3D(Point2D): pass >>> Point3D.__total__ True
Этот атрибут отражает только значение аргумента
total
для текущего классаTypedDict
, а не то, является ли этот класс семантически полным. Например, классTypedDict
с__total__
, установленным наTrue
, может иметь ключи, помеченныеNotRequired
, или наследоваться от другогоTypedDict
сtotal=False
. Поэтому для интроспекции обычно лучше использовать__required_keys__
и__optional_keys__
.
- __required_keys__¶
Added in version 3.9.
- __optional_keys__¶
Point2D.__required_keys__
иPoint2D.__optional_keys__
возвращают объектыfrozenset
, содержащие обязательные и необязательные ключи соответственно.Клавиши, отмеченные символом
Required
, всегда будут отображаться в__required_keys__
, а клавиши, отмеченные символомNotRequired
, всегда будут отображаться в__optional_keys__
.Для обратной совместимости с Python 3.10 и ниже также можно использовать наследование, чтобы объявить требуемые и необязательные ключи в одном и том же
TypedDict
. Это делается путем объявленияTypedDict
с одним значением аргументаtotal
, а затем наследования от него в другомTypedDict
с другим значением дляtotal
:>>> class Point2D(TypedDict, total=False): ... x: int ... y: int ... >>> class Point3D(Point2D): ... z: int ... >>> Point3D.__required_keys__ == frozenset({'z'}) True >>> Point3D.__optional_keys__ == frozenset({'x', 'y'}) True
Added in version 3.9.
Примечание
Если используется
from __future__ import annotations
или аннотации заданы в виде строк, аннотации не оцениваются при определенииTypedDict
. Поэтому интроспекция во время выполнения, на которую опираются__required_keys__
и__optional_keys__
, может работать некорректно, а значения атрибутов могут быть неверными.
Поддержка
ReadOnly
отражена в следующих атрибутах:- __readonly_keys__¶
Строка
frozenset
, содержащая имена всех ключей, доступных только для чтения. Ключи доступны только для чтения, если они содержат квалификаторReadOnly
.Added in version 3.13.
- __mutable_keys__¶
Строка
frozenset
, содержащая имена всех изменяемых ключей. Ключи являются изменяемыми, если они не содержат квалификатораReadOnly
.Added in version 3.13.
Примеры и подробные правила использования
TypedDict
см. в разделе PEP 589.Added in version 3.8.
Изменено в версии 3.11: Добавлена поддержка маркировки отдельных клавиш как
Required
илиNotRequired
. См. PEP 655.Изменено в версии 3.11: Добавлена поддержка общих
TypedDict
s.Изменено в версии 3.13: Удалена поддержка метода ключевого слова-аргумента для создания
TypedDict
s.Изменено в версии 3.13: Добавлена поддержка квалификатора
ReadOnly
.Утратил актуальность с версии 3.13, будет удален в версии 3.15: При использовании функционального синтаксиса для создания класса TypedDict непередача значения параметру „fields“ (
TD = TypedDict("TD")
) является устаревшей. ПередачаNone
в параметр „fields“ (TD = TypedDict("TD", None)
) также является устаревшей. Оба параметра будут запрещены в Python 3.15. Чтобы создать класс TypedDict с 0 полями, используйтеclass TD(TypedDict): pass
илиTD = TypedDict("TD", {})
.
Протоколы¶
Модуль типизации предоставляет следующие протоколы. Все они украшены символом @runtime_checkable
.
- class typing.SupportsAbs¶
ABC с одним абстрактным методом
__abs__
, который ковариантен по возвращаемому типу.
- class typing.SupportsBytes¶
ABC с одним абстрактным методом
__bytes__
.
- class typing.SupportsComplex¶
ABC с одним абстрактным методом
__complex__
.
- class typing.SupportsFloat¶
ABC с одним абстрактным методом
__float__
.
- class typing.SupportsIndex¶
ABC с одним абстрактным методом
__index__
.Added in version 3.8.
- class typing.SupportsInt¶
ABC с одним абстрактным методом
__int__
.
- class typing.SupportsRound¶
ABC с одним абстрактным методом
__round__
, который ковариантен по возвращаемому типу.
Азбука работы с IO¶
Функции и декораторы¶
- typing.cast(typ, val)¶
Приведите значение к определенному типу.
Это возвращает значение без изменений. Для программы проверки типов это сигнал о том, что возвращаемое значение имеет заданный тип, но во время выполнения мы намеренно ничего не проверяем (мы хотим, чтобы это было как можно быстрее).
- typing.assert_type(val, typ, /)¶
Попросите статическую программу проверки типов подтвердить, что val имеет выводимый тип typ.
Во время выполнения это ничего не делает: возвращает первый аргумент без изменений, без проверок и побочных эффектов, независимо от фактического типа аргумента.
Когда статическая программа проверки типов встречает вызов
assert_type()
, она выдает ошибку, если значение не имеет указанного типа:def greet(name: str) -> None: assert_type(name, str) # OK, inferred type of `name` is `str` assert_type(name, int) # type checker error
Эта функция полезна для обеспечения того, чтобы понимание скрипта программой проверки типов соответствовало намерениям разработчика:
def complex_function(arg: object): # Do some complex type-narrowing logic, # after which we hope the inferred type will be `int` ... # Test whether the type checker correctly understands our function assert_type(arg, int)
Added in version 3.11.
- typing.assert_never(arg, /)¶
Попросите программу проверки статических типов подтвердить, что строка кода недостижима.
Пример:
def int_or_str(arg: int | str) -> None: match arg: case int(): print("It's an int") case str(): print("It's a str") case _ as unreachable: assert_never(unreachable)
Здесь аннотации позволяют программе проверки типов сделать вывод, что последний случай никогда не может быть выполнен, поскольку
arg
является либоint
, либоstr
, и оба варианта покрываются предыдущими случаями.Если программа проверки типов обнаружит, что вызов
assert_never()
достижим, она выдаст ошибку. Например, если в аннотации типа дляarg
вместоint | str | float
, программа проверки типов выдаст ошибку, указывая, чтоunreachable
имеет типfloat
. Чтобы вызовassert_never
прошел проверку типов, предполагаемый тип передаваемого аргумента должен быть нижним типом,Never
, и ничем другим.Во время выполнения эта функция вызывает исключение.
См.также
Unreachable Code and Exhaustiveness Checking есть дополнительная информация о проверке исчерпываемости с помощью статической типизации.
Added in version 3.11.
- typing.reveal_type(obj, /)¶
Попросите статическую программу проверки типов определить предполагаемый тип выражения.
Когда программа проверки статических типов встречает вызов этой функции, она выдает диагностику с предполагаемым типом аргумента. Например:
x: int = 1 reveal_type(x) # Revealed type is "builtins.int"
Это может быть полезно, когда вы хотите отладить, как ваша программа проверки типов обрабатывает определенный фрагмент кода.
Во время выполнения эта функция выводит тип аргумента в
sys.stderr
и возвращает аргумент без изменений (что позволяет использовать вызов в выражении):x = reveal_type(1) # prints "Runtime type is int" print(x) # prints "1"
Обратите внимание, что тип во время выполнения может отличаться от типа, статически выведенного программой проверки типов (более или менее определенного).
Большинство программ проверки типов поддерживают
reveal_type()
в любом месте, даже если имя не импортировано изtyping
. Импорт имени изtyping
, однако, позволяет вашему коду работать без ошибок во время выполнения и более четко передает намерения.Added in version 3.11.
- @typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)¶
Декоратор для маркировки объекта как обеспечивающего
dataclass
-подобное поведение.dataclass_transform
может использоваться для декорирования класса, метакласса или функции, которая сама является декоратором. Наличие@dataclass_transform()
сообщает статической программе проверки типов, что декорированный объект выполняет «магию» во время выполнения, которая преобразует класс подобно@dataclasses.dataclass
.Пример использования с функцией-декоратором:
@dataclass_transform() def create_model[T](cls: type[T]) -> type[T]: ... return cls @create_model class CustomerModel: id: int name: str
На базовом классе:
@dataclass_transform() class ModelBase: ... class CustomerModel(ModelBase): id: int name: str
На метаклассе:
@dataclass_transform() class ModelMeta(type): ... class ModelBase(metaclass=ModelMeta): ... class CustomerModel(ModelBase): id: int name: str
Классы
CustomerModel
, определенные выше, будут обрабатываться программами проверки типов так же, как и классы, созданные с помощью@dataclasses.dataclass
. Например, программы проверки типов будут считать, что у этих классов есть методы__init__
, которые принимаютid
иname
.Декорируемый класс, метакласс или функция могут принимать следующие bool-аргументы, которые, как предполагают специалисты по проверке типов, имеют тот же эффект, что и в декораторе
@dataclasses.dataclass
:init
,eq
,order
,unsafe_hash
,frozen
,match_args
,kw_only
иslots
. Значение этих аргументов (True
илиFalse
) должно быть статически вычислено.Аргументы декоратора
dataclass_transform
могут быть использованы для настройки поведения по умолчанию декорируемого класса, метакласса или функции:- Параметры:
eq_default (bool) – Указывает, будет ли параметр
eq
приниматься заTrue
илиFalse
, если он опущен вызывающей стороной. По умолчанию принимается значениеTrue
.order_default (bool) – Указывает, будет ли параметр
order
приниматься заTrue
илиFalse
, если он опущен вызывающей стороной. По умолчанию принимается значениеFalse
.kw_only_default (bool) – Указывает, будет ли параметр
kw_only
приниматься заTrue
илиFalse
, если он опущен вызывающей стороной. По умолчанию принимается значениеFalse
.frozen_default (bool) – Указывает, будет ли параметр
frozen
приниматься заTrue
илиFalse
, если он опущен вызывающей стороной. По умолчаниюFalse
. … versionadded:: 3.12field_specifiers (tuple[Callable[..., Any], ...]) – Указывает статический список поддерживаемых классов или функций, описывающих поля, аналогично
dataclasses.field()
. По умолчанию принимает значение()
.**kwargs (Any) – Принимаются произвольные другие ключевые аргументы, чтобы обеспечить возможность будущих расширений.
Программы проверки типов распознают следующие необязательные параметры в спецификаторах полей:
¶ Имя параметра
Описание
init
Указывает, должно ли поле быть включено в синтезированный метод
__init__
. Если значение не указано, то по умолчаниюinit
принимает значениеTrue
.default
Предоставляет значение по умолчанию для поля.
default_factory
Предоставляет обратный вызов во время выполнения, который возвращает значение по умолчанию для поля. Если не указаны ни
default
, ниdefault_factory
, предполагается, что поле не имеет значения по умолчанию и должно быть предоставлено при инстанцировании класса.factory
Псевдоним для параметра
default_factory
в спецификаторах полей.kw_only
Указывает, должно ли поле быть помечено как доступное только для ключевых слов. Если
True
, то поле будет только для ключевых слов. ЕслиFalse
, то оно не будет предназначено только для ключевых слов. Если значение не указано, будет использоваться значение параметраkw_only
на объекте, украшенномdataclass_transform
, или, если оно не указано, будет использоваться значениеkw_only_default
наdataclass_transform
.alias
Предоставляет альтернативное имя для поля. Это альтернативное имя используется в синтезированном методе
__init__
.Во время выполнения этот декоратор записывает свои аргументы в атрибут
__dataclass_transform__
декорируемого объекта. Никаких других эффектов во время выполнения он не имеет.Более подробную информацию см. в разделе PEP 681.
Added in version 3.11.
- @typing.overload¶
Декоратор для создания перегруженных функций и методов.
Декоратор
@overload
позволяет описывать функции и методы, поддерживающие несколько различных комбинаций типов аргументов. За серией украшенных@overload
-определений должно следовать ровно одно не``@overload``-декорированное определение (для той же функции/метода).Определения с декорированием
@overload``предназначены только для проверки типов, поскольку они будут перезаписаны определением без ``@overload``декорирования. Определение без ``@overload
-декорирования, тем временем, будет использоваться во время выполнения, но должно быть проигнорировано программой проверки типов. Во время выполнения вызов@overload
-декорированной функции напрямую приведет к появлениюNotImplementedError
.Пример перегрузки, которая дает более точный тип, чем можно выразить с помощью объединения или переменной типа:
@overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): ... # actual implementation goes here
Более подробную информацию и сравнение с другими семантиками типизации см. в разделе PEP 484.
Изменено в версии 3.11: Перегруженные функции теперь можно интроспектировать во время выполнения с помощью
get_overloads()
.
- typing.get_overloads(func)¶
Возвращает последовательность
@overload
-декорированных определений для func.func - это объект функции для реализации перегруженной функции. Например, учитывая определение
process
в документации к@overload
,get_overloads(process)
вернет последовательность из трех объектов функций для трех определенных перегрузок. Если вызвать функцию без перегрузок,get_overloads()
вернет пустую последовательность.get_overloads()
можно использовать для интроспекции перегруженной функции во время выполнения.Added in version 3.11.
- typing.clear_overloads()¶
Очистите все зарегистрированные перегрузки во внутреннем реестре.
Это можно использовать для освобождения памяти, используемой реестром.
Added in version 3.11.
- @typing.final¶
Декоратор для указания финальных методов и финальных классов.
Украшение метода символом
@final
указывает программе проверки типов, что этот метод не может быть переопределен в подклассе. Украшение класса символом@final
указывает на то, что он не может быть подклассом.Например:
class Base: @final def done(self) -> None: ... class Sub(Base): def done(self) -> None: # Error reported by type checker ... @final class Leaf: ... class Other(Leaf): # Error reported by type checker ...
Проверка этих свойств во время выполнения не производится. Более подробную информацию см. в разделе PEP 591.
Added in version 3.8.
Изменено в версии 3.11: Теперь декоратор попытается установить атрибут
__final__
в значениеTrue
на декорируемом объекте. Таким образом, проверка типаif getattr(obj, "__final__", False)
может быть использована во время выполнения для определения того, был ли объектobj
помечен как final. Если декорируемый объект не поддерживает установку атрибутов, декоратор возвращает объект без изменений, не вызывая исключения.
- @typing.no_type_check¶
Декоратор, указывающий, что аннотации не являются подсказками типов.
Это работает как с классом, так и с функцией decorator. Для класса он применяется рекурсивно ко всем методам и классам, определенным в этом классе (но не к методам, определенным в его суперклассах или подклассах). Средства проверки типов будут игнорировать все аннотации в функции или классе с этим декоратором.
@no_type_check
мутирует украшенный объект на месте.
- @typing.no_type_check_decorator¶
Декоратор для придания другому декоратору эффекта
no_type_check()
.Это обернет декоратор чем-то, что обернет декорируемую функцию в
no_type_check()
.Утратил актуальность с версии 3.13, будет удален в версии 3.15: Ни одна программа проверки типов никогда не добавляла поддержку
@no_type_check_decorator
. Поэтому оно устарело и будет удалено в Python 3.15.
- @typing.override¶
Декоратор, указывающий, что метод в подклассе должен переопределять метод или атрибут в суперклассе.
Программы проверки типов должны выдавать ошибку, если метод, украшенный символом
@override
, на самом деле ничего не переопределяет. Это поможет предотвратить ошибки, которые могут возникнуть при изменении базового класса без эквивалентного изменения дочернего класса.Например:
class Base: def log_status(self) -> None: ... class Sub(Base): @override def log_status(self) -> None: # Okay: overrides Base.log_status ... @override def done(self) -> None: # Error reported by type checker ...
Проверка этого свойства во время выполнения не предусмотрена.
Декоратор попытается установить атрибут
__override__
в значениеTrue
на декорируемом объекте. Таким образом, проверка типаif getattr(obj, "__override__", False)
может быть использована во время выполнения для определения того, был ли объектobj
помечен как переопределение. Если декорируемый объект не поддерживает установку атрибутов, декоратор возвращает объект без изменений, не вызывая исключения.Более подробную информацию см. в разделе PEP 698.
Added in version 3.12.
- @typing.type_check_only¶
Декоратор, позволяющий пометить класс или функцию как недоступную во время выполнения.
Этот декоратор сам по себе недоступен во время выполнения. В основном он предназначен для пометки классов, определенных в файлах-заглушках типов, если реализация возвращает экземпляр приватного класса:
@type_check_only class Response: # private or not available at runtime code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...
Обратите внимание, что возвращать экземпляры частных классов не рекомендуется. Обычно предпочтительнее сделать такие классы общедоступными.
Помощники интроспекции¶
- typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)¶
Возвращает словарь, содержащий подсказки типов для функции, метода, модуля или объекта класса.
Часто это то же самое, что и
obj.__annotations__
. Кроме того, прямые ссылки, закодированные как строковые литералы, обрабатываются путем их оценки в пространствах именglobals
,locals
и (если применимо) type parameter. Для классаC
возвращается словарь, построенный путем объединения всех__annotations__
вдольC.__mro__
в обратном порядке.Функция рекурсивно заменяет все
Annotated[T, ...]
наT
, если толькоinclude_extras
не установлен наTrue
(см.Annotated
для получения дополнительной информации). Например:class Student(NamedTuple): name: Annotated[str, 'some marker'] assert get_type_hints(Student) == {'name': str} assert get_type_hints(Student, include_extras=False) == {'name': str} assert get_type_hints(Student, include_extras=True) == { 'name': Annotated[str, 'some marker'] }
Примечание
get_type_hints()
не работает с импортированными type aliases, содержащими прямые ссылки. Включение отложенной оценки аннотаций (PEP 563) может устранить необходимость в большинстве прямых ссылок.Изменено в версии 3.9: Добавлен параметр
include_extras
как часть параметра PEP 593. Дополнительные сведения см. в документации поAnnotated
.Изменено в версии 3.11: Ранее для аннотаций функций и методов добавлялось значение
Optional[t]
, если по умолчанию было установлено значениеNone
. Теперь аннотация возвращается без изменений.
- typing.get_origin(tp)¶
Получение нерасшифрованной версии типа: для объекта типизации вида
X[Y, Z, ...]
возвращаетсяX
.Если
X
является псевдонимом встроенного класса или классаcollections
, то он будет нормализован к исходному классу. ЕслиX
является экземпляромParamSpecArgs
илиParamSpecKwargs
, возвращается базовыйParamSpec
. Для неподдерживаемых объектов возвращаетсяNone
.Примеры:
assert get_origin(str) is None assert get_origin(Dict[str, int]) is dict assert get_origin(Union[int, str]) is Union P = ParamSpec('P') assert get_origin(P.args) is P assert get_origin(P.kwargs) is P
Added in version 3.8.
- typing.get_args(tp)¶
Получение аргументов типа со всеми выполненными заменами: для объекта типизации вида
X[Y, Z, ...]
возвращается(Y, Z, ...)
.Если
X
является объединением илиLiteral
содержится в другом родовом типе, порядок(Y, Z, ...)
может отличаться от порядка исходных аргументов[Y, Z, ...]
из-за кэширования типов. Возвращает()
для неподдерживаемых объектов.Примеры:
assert get_args(int) == () assert get_args(Dict[int, str]) == (int, str) assert get_args(Union[int, str]) == (int, str)
Added in version 3.8.
- typing.get_protocol_members(tp)¶
Возвращает набор членов, определенных в
Protocol
.>>> from typing import Protocol, get_protocol_members >>> class P(Protocol): ... def a(self) -> str: ... ... b: int >>> get_protocol_members(P) == frozenset({'a', 'b'}) True
Вызывает
TypeError
для аргументов, которые не являются протоколами.Added in version 3.13.
- typing.is_protocol(tp)¶
Определите, является ли тип
Protocol
.Например:
class P(Protocol): def a(self) -> str: ... b: int is_protocol(P) # => True is_protocol(int) # => False
Added in version 3.13.
- typing.is_typeddict(tp)¶
Проверьте, является ли тип типом
TypedDict
.Например:
class Film(TypedDict): title: str year: int assert is_typeddict(Film) assert not is_typeddict(list | str) # TypedDict is a factory for creating typed dicts, # not a typed dict itself assert not is_typeddict(TypedDict)
Added in version 3.10.
- class typing.ForwardRef¶
Класс, используемый для внутреннего типового представления прямых ссылок на строки.
Например,
List["SomeClass"]
неявно преобразуется вList[ForwardRef("SomeClass")]
.ForwardRef
не должен инстанцироваться пользователем, но может использоваться инструментами интроспекции.Примечание
Общие типы PEP 585, такие как
list["SomeClass"]
, не будут неявно преобразованы вlist[ForwardRef("SomeClass")]
и, следовательно, не будут автоматически разрешаться вlist[SomeClass]
.Added in version 3.7.4.
- typing.NoDefault¶
Объект-дозорный, используемый для указания того, что параметр типа не имеет значения по умолчанию. Например:
>>> T = TypeVar("T") >>> T.__default__ is typing.NoDefault True >>> S = TypeVar("S", default=None) >>> S.__default__ is None True
Added in version 3.13.
Постоянно¶
- typing.TYPE_CHECKING¶
Специальная константа, которая принимается за
True
сторонними статическими программами проверки типов. Во время выполнения она становитсяFalse
.Использование:
if TYPE_CHECKING: import expensive_mod def fun(arg: 'expensive_mod.SomeType') -> None: local_var: expensive_mod.AnotherType = other_fun()
Первая аннотация типа должна быть заключена в кавычки, что делает ее «прямой ссылкой», чтобы скрыть ссылку
expensive_mod
от времени выполнения интерпретатора. Аннотации типов для локальных переменных не оцениваются, поэтому вторую аннотацию не нужно заключать в кавычки.Примечание
Если используется
from __future__ import annotations
, аннотации не оцениваются во время определения функции. Вместо этого они хранятся в виде строк в__annotations__
. Это делает ненужным использование кавычек вокруг аннотации (см. PEP 563).Added in version 3.5.2.
Утраченные псевдонимы¶
Этот модуль определяет несколько устаревших псевдонимов для ранее существовавших классов стандартной библиотеки. Изначально они были включены в модуль типизации для поддержки параметризации этих общих классов с помощью []
. Однако в Python 3.9 эти псевдонимы стали излишними, когда соответствующие существующие классы были усовершенствованы для поддержки []
(см. PEP 585).
Лишние типы устарели, начиная с Python 3.9. Однако, хотя псевдонимы могут быть удалены в какой-то момент, в настоящее время удаление этих псевдонимов не планируется. Поэтому в настоящее время интерпретатор не выдает предупреждений об устаревании этих псевдонимов.
Если в какой-то момент будет решено удалить эти устаревшие псевдонимы, интерпретатор будет выдавать предупреждение об устаревании не менее чем за два выпуска до удаления. Псевдонимы гарантированно останутся в модуле типизации без предупреждений об устаревании по крайней мере до Python 3.14.
Программам проверки типов рекомендуется отмечать использование устаревших типов, если проверяемая ими программа использует минимальную версию Python 3.9 или новее.
Псевдонимы для встроенных типов¶
- class typing.Dict(dict, MutableMapping[KT, VT])¶
Утративший силу псевдоним для
dict
.Обратите внимание, что для аннотирования аргументов предпочтительнее использовать абстрактный тип коллекции, например
Mapping
, а неdict
илиtyping.Dict
.Этот тип можно использовать следующим образом:
def count_words(text: str) -> Dict[str, int]: ...
Не рекомендуется, начиная с версии 3.9:
builtins.dict
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.List(list, MutableSequence[T])¶
Утративший силу псевдоним для
list
.Обратите внимание, что для аннотирования аргументов предпочтительнее использовать абстрактный тип коллекции, например
Sequence
илиIterable
, а неlist
илиtyping.List
.Этот тип может быть использован следующим образом:
def vec2[T: (int, float)](x: T, y: T) -> List[T]: return [x, y] def keep_positives[T: (int, float)](vector: Sequence[T]) -> List[T]: return [item for item in vector if item > 0]
Не рекомендуется, начиная с версии 3.9:
builtins.list
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Set(set, MutableSet[T])¶
Утративший силу псевдоним для
builtins.set
.Обратите внимание, что для аннотирования аргументов предпочтительнее использовать абстрактный тип коллекции, например
AbstractSet
, а неset
илиtyping.Set
.Не рекомендуется, начиная с версии 3.9:
builtins.set
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.FrozenSet(frozenset, AbstractSet[T_co])¶
Утративший силу псевдоним для
builtins.frozenset
.Не рекомендуется, начиная с версии 3.9:
builtins.frozenset
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- typing.Tuple¶
Утративший силу псевдоним для
tuple
.В системе типов
tuple
иTuple
имеют особые случаи; подробнее см. в Аннотирование кортежей.Не рекомендуется, начиная с версии 3.9:
builtins.tuple
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Type(Generic[CT_co])¶
Утративший силу псевдоним для
type
.Подробнее об использовании
type
илиtyping.Type
в аннотациях типов см. в разделе Тип объектов класса.Added in version 3.5.2.
Не рекомендуется, начиная с версии 3.9:
builtins.type
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
Псевдонимы для типов в collections
¶
- class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])¶
Утративший силу псевдоним для
collections.defaultdict
.Added in version 3.5.2.
Не рекомендуется, начиная с версии 3.9:
collections.defaultdict
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])¶
Утративший силу псевдоним для
collections.OrderedDict
.Added in version 3.7.2.
Не рекомендуется, начиная с версии 3.9:
collections.OrderedDict
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])¶
Утративший силу псевдоним для
collections.ChainMap
.Added in version 3.6.1.
Не рекомендуется, начиная с версии 3.9:
collections.ChainMap
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Counter(collections.Counter, Dict[T, int])¶
Утративший силу псевдоним для
collections.Counter
.Added in version 3.6.1.
Не рекомендуется, начиная с версии 3.9:
collections.Counter
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Deque(deque, MutableSequence[T])¶
Утративший силу псевдоним для
collections.deque
.Added in version 3.6.1.
Не рекомендуется, начиная с версии 3.9:
collections.deque
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
Псевдонимы для других конкретных типов¶
- class typing.Pattern¶
- class typing.Match¶
Утраченные псевдонимы, соответствующие типам возврата из
re.compile()
иre.match()
.Эти типы (и соответствующие функции) являются общими для
AnyStr
.Pattern
может быть специализировано какPattern[str]
илиPattern[bytes]
;Match
может быть специализировано какMatch[str]
илиMatch[bytes]
.Не рекомендуется, начиная с версии 3.9: Классы
Pattern
иMatch
изre
теперь поддерживают[]
. См. PEP 585 и Общий тип псевдонима.
- class typing.Text¶
Утративший силу псевдоним для
str
.Text
предоставлен для обеспечения совместимого пути для кода Python 2: в Python 2Text
является псевдонимом дляunicode
.Используйте
Text
, чтобы указать, что значение должно содержать строку юникода, совместимую как с Python 2, так и с Python 3:def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'
Added in version 3.5.2.
Не рекомендуется, начиная с версии 3.11: Python 2 больше не поддерживается, и большинство программ проверки типов также больше не поддерживают проверку типа кода Python 2. Устранение псевдонима в настоящее время не планируется, но пользователям рекомендуется использовать
str
вместоText
.
Псевдонимы для контейнеров ABC в collections.abc
¶
- class typing.AbstractSet(Collection[T_co])¶
Утративший силу псевдоним для
collections.abc.Set
.Не рекомендуется, начиная с версии 3.9:
collections.abc.Set
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Collection(Sized, Iterable[T_co], Container[T_co])¶
Утративший силу псевдоним для
collections.abc.Collection
.Added in version 3.6.
Не рекомендуется, начиная с версии 3.9:
collections.abc.Collection
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Container(Generic[T_co])¶
Утративший силу псевдоним для
collections.abc.Container
.Не рекомендуется, начиная с версии 3.9:
collections.abc.Container
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]])¶
Утративший силу псевдоним для
collections.abc.ItemsView
.Не рекомендуется, начиная с версии 3.9:
collections.abc.ItemsView
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.KeysView(MappingView, AbstractSet[KT_co])¶
Утративший силу псевдоним для
collections.abc.KeysView
.Не рекомендуется, начиная с версии 3.9:
collections.abc.KeysView
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Mapping(Collection[KT], Generic[KT, VT_co])¶
Утративший силу псевдоним для
collections.abc.Mapping
.Этот тип можно использовать следующим образом:
def get_position_in_index(word_list: Mapping[str, int], word: str) -> int: return word_list[word]
Не рекомендуется, начиная с версии 3.9:
collections.abc.Mapping
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.MappingView(Sized)¶
Утративший силу псевдоним для
collections.abc.MappingView
.Не рекомендуется, начиная с версии 3.9:
collections.abc.MappingView
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.MutableMapping(Mapping[KT, VT])¶
Утративший силу псевдоним для
collections.abc.MutableMapping
.Не рекомендуется, начиная с версии 3.9:
collections.abc.MutableMapping
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.MutableSequence(Sequence[T])¶
Утративший силу псевдоним для
collections.abc.MutableSequence
.Не рекомендуется, начиная с версии 3.9:
collections.abc.MutableSequence
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.MutableSet(AbstractSet[T])¶
Утративший силу псевдоним для
collections.abc.MutableSet
.Не рекомендуется, начиная с версии 3.9:
collections.abc.MutableSet
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Sequence(Reversible[T_co], Collection[T_co])¶
Утративший силу псевдоним для
collections.abc.Sequence
.Не рекомендуется, начиная с версии 3.9:
collections.abc.Sequence
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.ValuesView(MappingView, Collection[_VT_co])¶
Утративший силу псевдоним для
collections.abc.ValuesView
.Не рекомендуется, начиная с версии 3.9:
collections.abc.ValuesView
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
Псевдонимы для асинхронных ABC в collections.abc
¶
- class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType])¶
Утративший силу псевдоним для
collections.abc.Coroutine
.Дисперсия и порядок переменных типа соответствуют переменным
Generator
, например:from collections.abc import Coroutine c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: y = await c # Inferred type of 'y' is int
Added in version 3.5.3.
Не рекомендуется, начиная с версии 3.9:
collections.abc.Coroutine
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType])¶
Утративший силу псевдоним для
collections.abc.AsyncGenerator
.Генератор async может быть аннотирован общим типом
AsyncGenerator[YieldType, SendType]
. Например:async def echo_round() -> AsyncGenerator[int, float]: sent = yield 0 while sent >= 0.0: rounded = await round(sent) sent = yield rounded
В отличие от обычных генераторов, асинхронные генераторы не могут возвращать значение, поэтому параметр типа
ReturnType
отсутствует. Как и в случае сGenerator
,SendType
ведет себя контравариантно.По умолчанию
SendType
принимает значениеNone
:async def infinite_stream(start: int) -> AsyncGenerator[int]: while True: yield start start = await increment(start)
Можно также задать этот тип в явном виде:
async def infinite_stream(start: int) -> AsyncGenerator[int, None]: while True: yield start start = await increment(start)
В качестве альтернативы укажите, что ваш генератор имеет тип возврата либо
AsyncIterable[YieldType]
, либоAsyncIterator[YieldType]
:async def infinite_stream(start: int) -> AsyncIterator[int]: while True: yield start start = await increment(start)
Added in version 3.6.1.
Не рекомендуется, начиная с версии 3.9:
collections.abc.AsyncGenerator
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.Изменено в версии 3.13: Параметр
SendType
теперь имеет значение по умолчанию.
- class typing.AsyncIterable(Generic[T_co])¶
Утративший силу псевдоним для
collections.abc.AsyncIterable
.Added in version 3.5.2.
Не рекомендуется, начиная с версии 3.9:
collections.abc.AsyncIterable
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.AsyncIterator(AsyncIterable[T_co])¶
Утративший силу псевдоним для
collections.abc.AsyncIterator
.Added in version 3.5.2.
Не рекомендуется, начиная с версии 3.9:
collections.abc.AsyncIterator
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Awaitable(Generic[T_co])¶
Утративший силу псевдоним для
collections.abc.Awaitable
.Added in version 3.5.2.
Не рекомендуется, начиная с версии 3.9:
collections.abc.Awaitable
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
Псевдонимы к другим азбукам в collections.abc
¶
- class typing.Iterable(Generic[T_co])¶
Утративший силу псевдоним для
collections.abc.Iterable
.Не рекомендуется, начиная с версии 3.9:
collections.abc.Iterable
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Iterator(Iterable[T_co])¶
Утративший силу псевдоним для
collections.abc.Iterator
.Не рекомендуется, начиная с версии 3.9:
collections.abc.Iterator
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- typing.Callable¶
Утративший силу псевдоним для
collections.abc.Callable
.О том, как использовать
collections.abc.Callable
иtyping.Callable
в аннотациях типов, см. в разделе Аннотирование вызываемых объектов.Не рекомендуется, начиная с версии 3.9:
collections.abc.Callable
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.Изменено в версии 3.10:
Callable
теперь поддерживаетParamSpec
иConcatenate
. Более подробную информацию см. в разделе PEP 612.
- class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])¶
Утративший силу псевдоним для
collections.abc.Generator
.Генератор может быть аннотирован общим типом
Generator[YieldType, SendType, ReturnType]
. Например:def echo_round() -> Generator[int, float, str]: sent = yield 0 while sent >= 0: sent = yield round(sent) return 'Done'
Обратите внимание, что в отличие от многих других родов в модуле типизации,
SendType
изGenerator
ведет себя контравариантно, а не ковариантно или инвариантно.Параметры
SendType
иReturnType
по умолчанию равныNone
:def infinite_stream(start: int) -> Generator[int]: while True: yield start start += 1
Также можно задать эти типы в явном виде:
def infinite_stream(start: int) -> Generator[int, None, None]: while True: yield start start += 1
В качестве альтернативы укажите, что ваш генератор имеет тип возврата либо
Iterable[YieldType]
, либоIterator[YieldType]
:def infinite_stream(start: int) -> Iterator[int]: while True: yield start start += 1
Не рекомендуется, начиная с версии 3.9:
collections.abc.Generator
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.Изменено в версии 3.13: Добавлены значения по умолчанию для типов send и return.
- class typing.Hashable¶
Утративший силу псевдоним для
collections.abc.Hashable
.Не рекомендуется, начиная с версии 3.12: Вместо этого используйте
collections.abc.Hashable
напрямую.
- class typing.Reversible(Iterable[T_co])¶
Утративший силу псевдоним для
collections.abc.Reversible
.Не рекомендуется, начиная с версии 3.9:
collections.abc.Reversible
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.
- class typing.Sized¶
Утративший силу псевдоним для
collections.abc.Sized
.Не рекомендуется, начиная с версии 3.12: Вместо этого используйте
collections.abc.Sized
напрямую.
Псевдонимы к contextlib
Азбука¶
- class typing.ContextManager(Generic[T_co, ExitT_co])¶
Утративший силу псевдоним для
contextlib.AbstractContextManager
.Первый параметр типа,
T_co
, представляет тип, возвращаемый методом__enter__()
. Необязательный второй параметр типа,ExitT_co
, который по умолчанию равенbool | None
, представляет тип, возвращаемый методом__exit__()
.Added in version 3.5.4.
Не рекомендуется, начиная с версии 3.9:
contextlib.AbstractContextManager
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.Изменено в версии 3.13: Добавлен необязательный второй параметр типа,
ExitT_co
.
- class typing.AsyncContextManager(Generic[T_co, AExitT_co])¶
Утративший силу псевдоним для
contextlib.AbstractAsyncContextManager
.Первый параметр типа,
T_co
, представляет тип, возвращаемый методом__aenter__()
. Необязательный второй параметр типа,AExitT_co
, который по умолчанию равенbool | None
, представляет тип, возвращаемый методом__aexit__()
.Added in version 3.6.2.
Не рекомендуется, начиная с версии 3.9:
contextlib.AbstractAsyncContextManager
теперь поддерживает подписку ([]
). См. PEP 585 и Общий тип псевдонима.Изменено в версии 3.13: Добавлен необязательный второй параметр типа,
AExitT_co
.
График устаревания основных функций¶
Некоторые функции в typing
являются устаревшими и могут быть удалены в будущих версиях Python. В следующей таблице для вашего удобства приведены основные устаревшие функции. Таблица может быть изменена, и в ней перечислены не все устаревшие функции.
Характеристика |
Утратил актуальность в |
Прогнозируемое удаление |
ПЭП/выпуск |
---|---|---|---|
|
3.9 |
Не определился (см. Утраченные псевдонимы для получения дополнительной информации) |
|
3.11 |
Не определившиеся |
||
3.12 |
Не определившиеся |
||
3.12 |
Не определившиеся |
||
3.13 |
3.15 |
||
3.13 |
3.18 |