typing — Поддержка подсказок типов
Добавлено в версии 3.5.
Исходный код: Lib/typing.py
Примечание
Среда выполнения Python не проверяет аннотации типов функций и переменных. Их могут использовать сторонние инструменты, например средства проверки типов, интегрированные среды разработки, линтеры и т. д.
Этот модуль обеспечивает поддержку подсказок типов во время выполнения.
Рассмотрим следующую функцию:
def surface_area_of_cube(edge_length: float) -> str:
return f"The surface area of the cube is {6 * edge_length ** 2}."
Функция surface_area_of_cube принимает аргумент, который, как ожидается, является экземпляром float, что указано в подсказке типа edge_length: float. Ожидается, что функция вернёт экземпляр str, что указано в подсказке -> str.
Подсказками типов могут быть простые классы, такие как float или str, но они могут быть и более сложными. Модуль typing предоставляет набор более сложных подсказок типов.
В модуль typing часто добавляются новые возможности. Пакет typing_extensions предоставляет обратные переносы этих новых возможностей для более старых версий Python.
См. также
- Шпаргалка по типизации
-
Краткий обзор подсказок типов (на сайте документации mypy)
- Раздел «Справочник по системе типов» в документации mypy
-
Система типизации Python стандартизирована с помощью PEP, поэтому этот справочник в целом применим к большинству средств проверки типов Python. (Некоторые части могут быть специфичны для mypy.)
- Статическая типизация в Python
-
Документация, не привязанная к конкретному средству проверки типов, написанная сообществом и описывающая возможности системы типов, полезные инструменты, связанные с типизацией, и лучшие практики типизации.
Спецификация системы типов Python
Актуальную каноническую спецификацию системы типов Python можно найти в документе Спецификация системы типов Python.
Псевдонимы типов
Псевдоним типа определяется с помощью оператора 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)
Для переменной типа UserId по-прежнему можно выполнять все операции int, но результат всегда будет иметь тип 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. Это полезно, когда нужно предотвращать логические ошибки с минимальными затратами во время выполнения.
Добавлено в версии 3.5.2.
Изменено в версии 3.10: NewType теперь является классом, а не функцией. В результате вызов NewType требует несколько больше ресурсов во время выполнения, чем вызов обычной функции.
Изменено в версии 3.11: Производительность вызова NewType восстановлена до уровня Python 3.9.
Аннотирование вызываемых объектов
Функции — или другие вызываемые объекты — можно аннотировать с помощью 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 не позволяет выразить сложные сигнатуры, например функции с переменным числом аргументов, перегруженные функции или функции с параметрами, доступными только по ключевому слову. Однако такие сигнатуры можно выразить, определив класс 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: ...
Обобщённые функции и классы можно параметризовать с помощью синтаксиса параметров типов:
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, переменные типов и объединения любых из этих типов. Например:
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, который является корнем иерархии метаклассов Python.
Аннотирование генераторов и сопрограмм
Генератор можно аннотировать с помощью обобщённого типа 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
Асинхронные генераторы обрабатываются аналогичным образом, но у них не указывается аргумент типа ReturnType (AsyncGenerator[YieldType, 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)
Сопрограммы можно аннотировать с помощью Coroutine[YieldType, SendType, ReturnType]. Обобщённые аргументы соответствуют аргументам 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
Определяемые пользователем обобщённые типы
Определяемый пользователем класс можно объявить обобщённым.
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 параметризован одной переменной типа 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]. Их поведение соответствует описанному выше поведению переменных типов, поскольку модуль typing рассматривает переменные спецификации параметров как особый вид переменных типов. Единственное исключение состоит в том, что вместо 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.
Определяемый пользователем обобщённый класс может иметь абстрактные базовые классы в качестве базовых классов без конфликта метаклассов. Обобщённые метаклассы не поддерживаются. Результат параметризации обобщённых типов кэшируется, а большинство типов в модуле typing хешируемы и допускают сравнение на равенство.
Тип 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 и не соответствует обычному идиоматичному коду 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: Устарело в пользу нового синтаксиса параметров типов. Используйте
class A[T: (str, bytes)]: ...вместо импортаAnyStr. Подробнее см. в PEP 695.В Python 3.16
AnyStrбудет удалён изtyping.__all__, а при обращении к нему или его импорте изtypingво время выполнения будут выдаваться предупреждения об устаревании.AnyStrбудет удалён изtypingв Python 3.18.
-
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.
Добавлено в версии 3.11.
-
typing.Never -
typing.NoReturn -
NeverиNoReturnпредставляют нижний тип — тип, у которого нет элементов.Их можно использовать, чтобы указать, что функция никогда не возвращает управление, например
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имеют одинаковое значение в системе типов, и средства статической проверки типов трактуют их эквивалентно.Добавлено в версии 3.6.2: Добавлен
NoReturn.Добавлен в версии 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в качестве аннотации возвращаемого значения, если при наследовании от класса метод не гарантирует возврат экземпляра подкласса: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.
Добавлено в версии 3.11.
-
-
typing.TypeAlias -
Специальная аннотация для явного объявления псевдонима типа.
Например:
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.
Добавлено в версии 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]
Однако это не относится к объединениям, на которые ссылаются через псевдоним типа, чтобы не требовать вычисления базового
TypeAliasType:type A = Union[int, str] Union[A, 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. См. выражения объединённых типов.
-
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: Теперь Optional можно записывать как
X | None. См. выражения объединённых типов.
-
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])Добавлено в версии 3.10.
См. также
-
PEP 612 — переменные спецификации параметров (PEP, в котором были введены
ParamSpecиConcatenate) ParamSpec- Аннотирование вызываемых объектов
-
PEP 612 — переменные спецификации параметров (PEP, в котором были введены
-
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 checkerLiteral[...]нельзя использовать как базовый класс. Во время выполнения в качестве аргумента типа дляLiteral[...]допускается произвольное значение, однако средства проверки типов могут накладывать ограничения. Дополнительные сведения о литеральных типах см. в PEP 586.Дополнительные сведения:
- Аргументы должны быть литеральными значениями, и должен быть указан хотя бы один аргумент.
-
Вложенные типы
Literalуплощаются, например:assert Literal[Literal[1, 2], 3] == Literal[1, 2, 3]
Однако это не относится к типам
Literal, на которые ссылаются через псевдоним типа, чтобы не требовать вычисления базовогоTypeAliasType:type A = Literal[1, 2] assert Literal[A, 3] != Literal[1, 2, 3]
-
Повторяющиеся аргументы пропускаются, например:
assert Literal[1, 2, 1] == Literal[1, 2]
-
При сравнении литералов порядок аргументов не учитывается, например:
assert Literal[1, 2] == Literal[2, 1]
- Нельзя создавать подклассы
Literalили экземпляры этого типа. - Нельзя записывать
Literal[X][Y].
Добавлено в версии 3.8.
Изменено в версии 3.9.1: Теперь
Literalудаляет повторяющиеся параметры. Сравнение объектовLiteralна равенство больше не зависит от порядка. Теперь объектыLiteralвызывают исключениеTypeErrorпри сравнении на равенство, если один из их параметров не является хешируемым.
-
typing.ClassVar -
Специальная конструкция типа для обозначения переменных класса.
Как описано в PEP 526, аннотация переменной, обёрнутая в ClassVar, указывает, что данный атрибут предназначен для использования в качестве переменной класса и не должен задаваться в экземплярах этого класса. Пример использования:
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variableClassVarпринимает только типы и не может быть проиндексирован дополнительно.ClassVarне является классом и не должен использоваться сisinstance()илиissubclass().ClassVarне меняет поведение Python во время выполнения, но может использоваться сторонними средствами проверки типов. Например, средство проверки типов может пометить следующий код как ошибочный:enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OKДобавлено в версии 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.
Добавлено в версии 3.8.
-
typing.Required -
Специальная конструкция типизации, помечающая ключ
TypedDictкак обязательный.Это особенно полезно для
total=FalseTypedDict. Дополнительные сведения см. вTypedDictи PEP 655.Добавлено в версии 3.11.
-
typing.NotRequired -
Специальная конструкция типизации, помечающая ключ
TypedDictкак потенциально отсутствующий.Дополнительные сведения см. в
TypedDictи PEP 655.Добавлено в версии 3.11.
-
typing.ReadOnly -
Специальная конструкция типизации, помечающая элемент
TypedDictкак доступный только для чтения.Например:
class Movie(TypedDict): title: ReadOnly[str] year: int def mutate_movie(m: Movie) -> None: m["year"] = 1999 # allowed m["title"] = "The Matrix" # typechecker error
Это свойство не проверяется во время выполнения.
Дополнительные сведения см. в
TypedDictи PEP 705.Добавлено в версии 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 a1 = Annotated[int, ValueRange(3, 10), ctype("char")] a2 = Annotated[int, ctype("char"), ValueRange(3, 10)] assert a1 != a2 # Order mattersИнструменту, обрабатывающему аннотации, решать, разрешено ли клиенту добавлять несколько элементов метаданных к одной аннотации и как объединять такие аннотации.
Вложенные типы
Annotatedуплощаются. Порядок элементов метаданных начинается с самой внутренней аннотации:assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ]Однако это не относится к типам
Annotated, на которые ссылаются через псевдоним типа, чтобы не требовать вычисления базовогоTypeAliasType:type From3To10[T] = Annotated[T, ValueRange(3, 10)] assert Annotated[From3To10[int], 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] = Annotated[T1, T2, T3, ..., Ann1] # NOT valid
где
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')Чтобы получить исходный тип, обёрнутый в
Annotated, используйте атрибут__origin__:>>> from typing import Annotated, get_origin >>> Password = Annotated[str, "secret"] >>> Password.__origin__ <class 'str'>
Обратите внимание, что вызов
get_origin()вернёт самAnnotated:>>> get_origin(Password) typing.Annotated
См. также
- PEP 593 — гибкие аннотации функций и переменных
-
PEP, в котором
Annotatedдобавлен в стандартную библиотеку.
Добавлено в версии 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).Добавлено в версии 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.
Добавлено в версии 3.10.
-
typing.Unpack -
Оператор типизации, концептуально обозначающий объект как распакованный.
Например, применение оператора распаковки
*к кортежу переменных типа эквивалентно использованиюUnpackдля обозначения этого кортежа переменных типа как распакованного:Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Effectively does: tup: tuple[Unpack[Ts]]Фактически, в контексте типов
typing.TypeVarTupleиbuiltins.tupleUnpackи*можно использовать взаимозаменяемо. В более старых версиях Python можно встретить явное использованиеUnpack, поскольку*нельзя было использовать в некоторых местах:# 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-compatibleUnpackтакже можно использовать вместе с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.Добавлено в версии 3.11.
Создание обобщённых типов и псевдонимов типов
Следующие классы не следует использовать непосредственно в качестве аннотаций. Они предназначены для использования как строительные блоки при создании обобщённых типов и псевдонимов типов.
Эти объекты можно создавать с помощью специального синтаксиса (списки параметров типа и инструкции type). Для совместимости с Python 3.11 и более ранними версиями их также можно создавать без специального синтаксиса, как описано ниже.
-
class typing.Generic -
Абстрактный базовый класс для обобщённых типов.
Обобщённый тип обычно объявляется путём добавления списка параметров типа после имени класса:
class Mapping[KT, VT]: def __getitem__(self, key: KT) -> VT: ... # Etc.Такой класс неявно наследуется от
Generic. Семантика этого синтаксиса во время выполнения описана в Справочнике по языку.Затем этот класс можно использовать следующим образом:
def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return defaultЗдесь квадратные скобки после имени функции обозначают обобщённую функцию.
Для обратной совместимости обобщённые классы также можно объявлять, явно наследуясь от
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) -
Переменная типа.
Предпочтительный способ создания переменной типа — использовать специальный синтаксис для обобщённых функций, обобщённых классов и обобщённых псевдонимов типов:
class Sequence[T]: # T is a TypeVar ...Этот синтаксис также можно использовать для создания ограниченных переменных типа и переменных типа с ограничениями:
class StrSequence[S: str]: # S is a TypeVar with a `str` upper bound; ... # we can say that S is "bounded by `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Обратите внимание, что переменные типа могут быть ограниченными сверху, ограниченными или не иметь ограничений, но не могут быть одновременно ограниченными сверху и ограниченными.
Ковариантность или контравариантность переменных типа выводится анализаторами типов, если переменные создаются с помощью синтаксиса параметров типа или передаётся
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 или Protocol) или даже объединение типов:
# 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__ -
Указывает, была ли переменная типа явно помечена как ковариантная.
-
__contravariant__ -
Указывает, была ли переменная типа явно помечена как контравариантная.
-
__infer_variance__ -
Указывает, должны ли анализаторы типов выводить вариантность переменной типа.
Добавлено в версии 3.12.
-
__bound__ -
Верхняя граница переменной типа, если она задана.
Изменено в версии 3.12: Для переменных типа, созданных с помощью синтаксиса параметров типа, граница вычисляется только при обращении к атрибуту, а не при создании переменной типа (см. раздел Отложенное вычисление).
-
__constraints__ -
Кортеж, содержащий ограничения переменной типа, если они заданы.
Изменено в версии 3.12: Для переменных типа, созданных с помощью синтаксиса параметров типа, ограничения вычисляются только при обращении к атрибуту, а не при создании переменной типа (см. раздел Отложенное вычисление).
-
__default__ -
Значение по умолчанию переменной типа или
typing.NoDefault, если значение по умолчанию не задано.Добавлено в версии 3.13.
-
has_default() -
Возвращает, задано ли для переменной типа значение по умолчанию. Это равносильно проверке того, что
__default__не является синглтономtyping.NoDefault, за исключением того, что этот метод не вызывает вычисление вычисляемого отложенно значения по умолчанию.Добавлено в версии 3.13.
Изменено в версии 3.12: Теперь переменные типа можно объявлять с помощью синтаксиса параметров типа, представленного в PEP 695. Добавлен параметр
infer_variance.Изменено в версии 3.13: Добавлена поддержка значений по умолчанию.
-
-
class typing.TypeVarTuple(name, *, default=typing.NoDefault) -
Кортеж переменных типа. Специализированная форма переменной типа, поддерживающая вариативные обобщения.
Кортежи переменных типа можно объявлять в списках параметров типа, ставя одну звёздочку (
*) перед именем: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, если значение по умолчанию не задано.Добавлено в версии 3.13.
-
has_default() -
Возвращает, задано ли для кортежа переменных типа значение по умолчанию. Это равносильно проверке того, что
__default__не является синглтономtyping.NoDefault, за исключением того, что этот метод не вызывает вычисление вычисляемого отложенно значения по умолчанию.Добавлено в версии 3.13.
Добавлено в версии 3.11.
Изменено в версии 3.12: Теперь кортежи переменных типа можно объявлять с помощью синтаксиса параметров типа, представленного в PEP 695.
Изменено в версии 3.13: Добавлена поддержка значений по умолчанию.
-
-
class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault) -
Переменная спецификации параметров. Специализированная версия переменных типа.
В списках параметров типа спецификации параметров можно объявлять, ставя две звёздочки (
**):type IntFunc[**P] = Callable[P, int]
Для совместимости с Python 3.11 и более ранними версиями объекты
ParamSpecтакже можно создавать следующим образом:P = ParamSpec('P')Переменные спецификации параметров существуют прежде всего для статических анализаторов типов. Они используются для передачи типов параметров одной вызываемой сущности другой — такой шаблон часто встречается в функциях высшего порядка и декораторах. Они допустимы только при использовании в
Concatenate, в качестве первого аргумента дляCallableили в качестве параметров пользовательских обобщённых типов. Подробнее об обобщённых типах см. в разделе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. -
В теле декоратора
add_loggingможет потребоватьсяcast()при возврате функции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, если значение по умолчанию не задано.Добавлено в версии 3.13.
-
has_default() -
Возвращает, задано ли для спецификации параметров значение по умолчанию. Это равносильно проверке того, что
__default__не является синглтономtyping.NoDefault, за исключением того, что этот метод не вызывает вычисление вычисляемого отложенно значения по умолчанию.Добавлено в версии 3.13.
Переменные спецификации параметров, созданные с помощью
covariant=Trueилиcontravariant=True, можно использовать для объявления ковариантных или контравариантных обобщённых типов. Также принимается аргументbound, как и в случае сTypeVar. Однако фактическая семантика этих ключевых слов ещё не определена.Добавлено в версии 3.10.
Изменено в версии 3.12: Теперь спецификации параметров можно объявлять с помощью синтаксиса параметров типа, представленного в PEP 695.
Изменено в версии 3.13: Добавлена поддержка значений по умолчанию.
Примечание
Сериализовать с помощью pickle можно только переменные спецификации параметров, определённые в глобальной области видимости.
См. также
-
PEP 612 — переменные спецификации параметров (PEP, в котором представлены
ParamSpecиConcatenate) 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Добавлено в версии 3.10.
-
class typing.TypeAliasType(name, value, *, type_params=()) -
Тип псевдонимов типов, созданных с помощью инструкции
type.Пример:
>>> type Alias = int >>> type(Alias) <class 'typing.TypeAliasType'>
Добавлено в версии 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__ -
Значение псевдонима типа. Оно вычисляется отложенно, поэтому имена, используемые в определении псевдонима, разрешаются только при обращении к атрибуту
__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; оба входят в APInamedtuple().)Подклассы
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 T = TypeVar("T") 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 без полей, используйтеclass NT(NamedTuple): passилиNT = NamedTuple("NT", []).
-
class typing.NewType(name, tp) -
Вспомогательный класс для создания различных типов с малыми накладными расходами.
Средство проверки типов считает
NewTypeотдельным типом. Однако во время выполнения вызовNewTypeвозвращает переданный ему аргумент без изменений.Использование:
UserId = NewType('UserId', int) # Declare the NewType "UserId" first_user = UserId(1) # "UserId" returns the argument unchanged at runtime-
__module__ -
Модуль, в котором определён новый тип.
-
__name__ -
Имя нового типа.
-
__supertype__ -
Тип, на основе которого создан новый тип.
Добавлено в версии 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()(описанного далее), выступают в роли простых протоколов времени выполнения: они проверяют только наличие заданных атрибутов, игнорируя их сигнатуры и типы. Классы-протоколы без этого декоратора нельзя использовать в качестве второго аргументаisinstance()илиissubclass().Классы-протоколы могут быть обобщёнными, например:
class GenProto[T](Protocol): def meth(self) -> T: ...В коде, который должен быть совместим с Python 3.11 и более ранними версиями, обобщённые протоколы можно записать следующим образом:
T = TypeVar("T") class GenProto(Protocol[T]): def meth(self) -> T: ...Добавлено в версии 3.8.
-
@typing.runtime_checkable -
Помечает класс-протокол как протокол времени выполнения.
Такой протокол можно использовать с
isinstance()иissubclass(). Это позволяет выполнять простую структурную проверку, очень похожую на проверки «узкоспециализированных» классов в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)При применении к классу, не являющемуся протоколом, этот декоратор вызывает исключение
TypeError.Примечание
runtime_checkable()проверяет только наличие требуемых методов или атрибутов, но не их сигнатуры и типы. Например,ssl.SSLObjectявляется классом, поэтому он проходит проверкуissubclass()для Callable. Однако методssl.SSLObject.__init__существует только для вызова исключенияTypeErrorс более информативным сообщением, поэтому вызвать (создать экземпляр)ssl.SSLObjectневозможно.Примечание
Проверка
isinstance()для протокола, проверяемого во время выполнения, может оказаться неожиданно медленной по сравнению с проверкойisinstance()для класса, не являющегося протоколом. В коде, чувствительном к производительности, для структурных проверок рассмотрите альтернативные способы, например вызовыhasattr().Добавлено в версии 3.8.
Изменено в версии 3.12: Внутренняя реализация проверок
isinstance()для протоколов времени выполнения теперь используетinspect.getattr_static()для поиска атрибутов (раньше использовалсяhasattr()). В результате некоторые объекты, которые раньше считались экземплярами протокола времени выполнения, в Python 3.12 и более поздних версиях могут перестать считаться его экземплярами, и наоборот. Большинство пользователей вряд ли заметит это изменение.Изменено в версии 3.12: Теперь участники протокола времени выполнения считаются «замороженными» во время выполнения сразу после создания класса. Добавлять атрибуты в протокол времени выполнения с помощью monkey patching по-прежнему можно, но это не повлияет на проверки
isinstance()при сопоставлении объектов с протоколом. Подробнее см. в разделе Что нового в 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})Этот функциональный синтаксис позволяет определять ключи, которые не являются допустимыми идентификаторами, например если они являются ключевыми словами или содержат дефисы, либо если имена ключей не должны подвергаться изменению имён, как обычные приватные имена:
# raises SyntaxError class Point2D(TypedDict): in: int # 'in' is a keyword x-y: int # name with hyphens class Definition(TypedDict): __schema: str # mangled to `_Definition__schema` # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int}) Definition = TypedDict('Definition', {'__schema': str}) # not mangledПо умолчанию в
TypedDictдолжны присутствовать все ключи. Отдельные ключи можно пометить как необязательные с помощьюNotRequired:class Point2D(TypedDict): x: int y: int label: NotRequired[str] # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})Это означает, что в
Point2DTypedDictключlabelможно не указывать.Также можно сделать все ключи необязательными по умолчанию, указав
Falseв качестве значения параметра totality:class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)Это означает, что в
Point2DTypedDictможно не указывать любые ключи. От средства проверки типов требуется поддерживать в качестве значения аргументаtotalтолько литералыFalseилиTrue. ЗначениеTrueиспользуется по умолчанию и делает обязательными все элементы, определённые в теле класса.Отдельные ключи
total=FalseTypedDictможно пометить как обязательные с помощью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: intTypedDictне может наследовать класс, не являющийся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 TypeErrorTypedDictможет быть обобщённым: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можно получить через словари аннотаций (дополнительную информацию о лучших практиках работы с аннотациями см. в разделе Рекомендации по работе с аннотациями), а также через__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__ -
Добавлено в версии 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Добавлено в версии 3.9.
Примечание
Если используется
from __future__ import annotationsили аннотации заданы в виде строк, при определенииTypedDictаннотации не вычисляются. Поэтому интроспекция во время выполнения, на которую опираются__required_keys__и__optional_keys__, может работать неправильно, а значения атрибутов могут быть некорректными.
Поддержка
ReadOnlyотражена в следующих атрибутах:-
__readonly_keys__ -
Объект
frozenset, содержащий имена всех ключей только для чтения. Ключи доступны только для чтения, если они имеют квалификаторReadOnly.Добавлено в версии 3.13.
-
__mutable_keys__ -
Объект
frozenset, содержащий имена всех изменяемых ключей. Ключи являются изменяемыми, если у них нет квалификатораReadOnly.Добавлено в версии 3.13.
Дополнительные примеры и подробные правила использования
TypedDictсм. в PEP 589.Добавлено в версии 3.8.
Изменено в версии 3.11: Добавлена поддержка пометки отдельных ключей как
RequiredилиNotRequired. См. PEP 655.Изменено в версии 3.11: Добавлена поддержка обобщённых
TypedDict.Изменено в версии 3.13: Удалена поддержка создания
TypedDictс помощью именованных аргументов.Изменено в версии 3.13: Добавлена поддержка квалификатора
ReadOnly.Устарело с версии 3.13, будет удалено в версии 3.15: При использовании функционального синтаксиса для создания класса TypedDict устарело не передавать значение параметру ‘fields’ (
TD = TypedDict("TD")). ПередачаNoneпараметру ‘fields’ (TD = TypedDict("TD", None)) также устарела. Оба варианта будут запрещены в Python 3.15. Чтобы создать класс TypedDict без полей, используйтеclass TD(TypedDict): passилиTD = TypedDict("TD", {}). -
Протоколы
Модуль typing предоставляет следующие протоколы. Все они декорированы с помощью @runtime_checkable.
-
class typing.SupportsAbs -
Абстрактный базовый класс с одним абстрактным методом
__abs__, ковариантным по типу возвращаемого значения.
-
class typing.SupportsBytes -
Абстрактный базовый класс с одним абстрактным методом
__bytes__.
-
class typing.SupportsComplex -
Абстрактный базовый класс с одним абстрактным методом
__complex__.
-
class typing.SupportsFloat -
Абстрактный базовый класс с одним абстрактным методом
__float__.
-
class typing.SupportsIndex -
Абстрактный базовый класс с одним абстрактным методом
__index__.Добавлено в версии 3.8.
-
class typing.SupportsInt -
Абстрактный базовый класс с одним абстрактным методом
__int__.
-
class typing.SupportsRound -
Абстрактный базовый класс с одним абстрактным методом
__round__, ковариантным по типу возвращаемого значения.
Абстрактные базовые классы для работы с вводом-выводом
-
class typing.IO -
class typing.TextIO -
class typing.BinaryIO -
Обобщённый тип
IO[AnyStr]и его подклассыTextIO(IO[str])иBinaryIO(IO[bytes])обозначают типы потоков ввода-вывода, например тех, которые возвращаетopen().
Функции и декораторы
-
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)Добавлено в версии 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— и никаким другим.Во время выполнения при вызове функция возбуждает исключение.
См. также
В статье Недостижимый код и проверка полноты приведены дополнительные сведения о проверке полноты с помощью статической типизации.
Добавлено в версии 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позволяет запускать код без ошибок во время выполнения и яснее выражает намерение.Добавлено в версии 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.Декорированный класс, метакласс или функция могут принимать следующие логические аргументы, эффект которых средства проверки типов будут считать таким же, как у декоратора
@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.Добавлено в версии 3.12.
-
field_specifiers (tuple[Callable[..., Any], ...]) – Указывает статический список поддерживаемых классов или функций, описывающих поля, подобно
dataclasses.field(). По умолчанию —(). - **kwargs (Any) – Принимаются любые другие именованные аргументы, чтобы обеспечить возможность будущих расширений.
-
eq_default (bool) – Указывает, считается ли параметр
Средства проверки типов распознают следующие необязательные параметры у спецификаторов полей:
Распознаваемые параметры спецификаторов полей Имя параметра
Описание
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.
Добавлено в версии 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()можно использовать для анализа перегруженной функции во время выполнения.Добавлено в версии 3.11.
-
typing.clear_overloads() -
Удаляет все зарегистрированные перегрузки из внутреннего реестра.
Это можно использовать, чтобы освободить память, занятую реестром.
Добавлено в версии 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.
Добавлено в версии 3.8.
Изменено в версии 3.11: Теперь декоратор пытается установить атрибут
__final__в значениеTrueу декорированного объекта. Поэтому во время выполнения можно использовать проверку наподобиеif getattr(obj, "__final__", False), чтобы определить, помечен ли объектobjкак конечный. Если декорированный объект не поддерживает установку атрибутов, декоратор возвращает объект без изменений и не возбуждает исключение.
-
@typing.no_type_check -
Декоратор, указывающий, что аннотации не являются подсказками типов.
Работает как декоратор класса или функции. Для класса действие рекурсивно распространяется на все методы и классы, определённые в этом классе (но не на методы, определённые в его суперклассах или подклассах). Средства проверки типов игнорируют все аннотации в функции или классе с этим декоратором.
@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.
Добавлено в версии 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__, но эта функция вносит в словарь аннотаций следующие изменения:- Строковые прямые ссылки и объекты
ForwardRefобрабатываются путём их вычисления в пространствах имён globalns, localns и (если применимо) параметров типа объекта obj. Если globalns или localns не заданы, соответствующие словари пространств имён выводятся из obj. -
Noneзаменяется наtypes.NoneType. - Если к obj применён декоратор
@no_type_check, возвращается пустой словарь. - Если obj является классом
C, функция возвращает словарь, объединяющий аннотации базовых классовCс аннотациями самогоC. Для этого функция проходит поC.__mro__и последовательно объединяет словари__annotations__. Аннотации классов, расположенных раньше в порядке разрешения методов, всегда имеют приоритет над аннотациями классов, расположенных позже. - Функция рекурсивно заменяет все вхождения
Annotated[T, ...]наT, если только для include_extras не задано значениеTrue(дополнительные сведения см. в описанииAnnotated).
См. также
inspect.get_annotations()— низкоуровневую функцию, которая возвращает аннотации более непосредственно.Примечание
Если какие-либо прямые ссылки в аннотациях obj не удаётся разрешить или они не являются допустимым кодом Python, функция возбуждает исключение, например
NameError. Такое может произойти, например, с импортированными псевдонимами типов, содержащими прямые ссылки, или с именами, импортированными под условиемif TYPE_CHECKING.Изменено в версии 3.9: Добавлен параметр
include_extrasв рамках PEP 593. Дополнительные сведения см. в документации кAnnotated.Изменено в версии 3.11: Ранее для аннотаций функций и методов добавлялось
Optional[t], если значение по умолчанию было равноNone. Теперь аннотация возвращается без изменений. - Строковые прямые ссылки и объекты
-
typing.get_origin(tp) -
Получить тип без параметров: для объекта typing вида
X[Y, Z, ...]вернутьX.Если
Xявляется псевдонимом модуля typing для встроенного класса или класса из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 assert get_origin(Annotated[str, "metadata"]) is Annotated P = ParamSpec('P') assert get_origin(P.args) is P assert get_origin(P.kwargs) is PДобавлено в версии 3.8.
-
typing.get_args(tp) -
Получить аргументы типа с учётом всех подстановок: для объекта typing вида
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)
Добавлено в версии 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.Добавлено в версии 3.13.
-
typing.is_protocol(tp) -
Определить, является ли тип
Protocol.Например:
class P(Protocol): def a(self) -> str: ... b: int is_protocol(P) # => True is_protocol(int) # => FalseДобавлено в версии 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)Добавлено в версии 3.10.
-
class typing.ForwardRef -
Класс для внутреннего представления строковых прямых ссылок в модуле typing.
Например,
List["SomeClass"]неявно преобразуется вList[ForwardRef("SomeClass")]. Пользователь не должен создавать экземплярыForwardRef, однако этот класс могут использовать средства интроспекции.Примечание
Обобщённые типы PEP 585, например
list["SomeClass"], не будут неявно преобразованы вlist[ForwardRef("SomeClass")]и поэтому не будут автоматически разрешаться вlist[SomeClass].Добавлено в версии 3.7.4.
-
typing.NoDefault -
Объект-маркер, указывающий, что у параметра типа нет значения по умолчанию. Например:
>>> T = TypeVar("T") >>> T.__default__ is typing.NoDefault True >>> S = TypeVar("S", default=None) >>> S.__default__ is None TrueДобавлено в версии 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).Добавлено в версии 3.5.2.
Устаревшие псевдонимы
Этот модуль определяет несколько устаревших псевдонимов для уже существующих классов стандартной библиотеки. Изначально они были включены в модуль typing для поддержки параметризации этих обобщённых классов с помощью []. Однако в Python 3.9 псевдонимы стали избыточными, когда соответствующие существовавшие ранее классы получили поддержку [] (см. PEP 585).
Избыточные типы объявлены устаревшими начиная с Python 3.9. Однако, хотя псевдонимы могут быть удалены в какой-либо момент, в настоящее время удаление этих псевдонимов не планируется. Поэтому интерпретатор пока не выдаёт предупреждений об устаревании для этих псевдонимов.
Если в какой-либо момент будет принято решение удалить эти устаревшие псевдонимы, интерпретатор будет выдавать предупреждения об устаревании как минимум в течение двух выпусков до их удаления. Гарантируется, что псевдонимы останутся в модуле typing без предупреждений об устаревании как минимум до Python 3.14.
Рекомендуется, чтобы средства проверки типов отмечали использование устаревших типов, если проверяемая программа рассчитана на Python версии 3.9 или новее.
Псевдонимы встроенных типов
-
class typing.Dict(dict, MutableMapping[KT, VT]) -
Устаревший псевдоним для
dict.Обратите внимание: для аннотирования аргументов предпочтительно использовать абстрактный тип коллекции, например
Mapping, а неdictилиtyping.Dict.Устарело начиная с версии 3.9:
builtins.dictтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.List(list, MutableSequence[T]) -
Устаревший псевдоним для
list.Обратите внимание: для аннотирования аргументов предпочтительно использовать абстрактный тип коллекции, например
SequenceилиIterable, а неlistилиtyping.List.Устарело начиная с версии 3.9:
builtins.listтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Set(set, MutableSet[T]) -
Устаревший псевдоним для
builtins.set.Обратите внимание: для аннотирования аргументов предпочтительно использовать абстрактный тип коллекции, например
collections.abc.Set, а неsetилиtyping.Set.Устарело начиная с версии 3.9:
builtins.setтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.FrozenSet(frozenset, AbstractSet[T_co]) -
Устаревший псевдоним для
builtins.frozenset.Устарело начиная с версии 3.9:
builtins.frozensetтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
typing.Tuple -
Устаревший псевдоним для
tuple.tupleиTupleобрабатываются в системе типов особым образом; дополнительные сведения см. в разделе Annotating tuples.Устарело начиная с версии 3.9:
builtins.tupleтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Type(Generic[CT_co]) -
Устаревший псевдоним для
type.Сведения об использовании
typeилиtyping.Typeв аннотациях типов см. в разделе The type of class objects.Добавлено в версии 3.5.2.
Устарело начиная с версии 3.9:
builtins.typeтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
Псевдонимы типов из collections
-
class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT]) -
Устаревший псевдоним для
collections.defaultdict.Добавлено в версии 3.5.2.
Устарело начиная с версии 3.9:
collections.defaultdictтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT]) -
Устаревший псевдоним для
collections.OrderedDict.Добавлено в версии 3.7.2.
Устарело начиная с версии 3.9:
collections.OrderedDictтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT]) -
Устаревший псевдоним для
collections.ChainMap.Добавлено в версии 3.6.1.
Устарело начиная с версии 3.9:
collections.ChainMapтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Counter(collections.Counter, Dict[T, int]) -
Устаревший псевдоним для
collections.Counter.Добавлено в версии 3.6.1.
Устарело начиная с версии 3.9:
collections.Counterтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Deque(deque, MutableSequence[T]) -
Устаревший псевдоним для
collections.deque.Добавлено в версии 3.6.1.
Устарело начиная с версии 3.9:
collections.dequeтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
Псевдонимы других конкретных типов
-
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 и Generic Alias Type.
-
class typing.Text -
Устаревший псевдоним для
str.Textпредоставлен для обеспечения совместимого с будущими версиями способа перехода для кода Python 2: в Python 2Textявляется псевдонимомunicode.Используйте
Text, чтобы указать, что значение должно содержать строку Unicode способом, совместимым как с Python 2, так и с Python 3:def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'Добавлено в версии 3.5.2.
Устарело начиная с версии 3.11: Python 2 больше не поддерживается, и большинство средств проверки типов также больше не проверяют типы в коде Python 2. Удаление псевдонима в настоящее время не планируется, но рекомендуется использовать
strвместоText.
Псевдонимы абстрактных базовых классов контейнеров из collections.abc
-
class typing.AbstractSet(Collection[T_co]) -
Устаревший псевдоним для
collections.abc.Set.Устарело начиная с версии 3.9:
collections.abc.Setтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.ByteString(Sequence[int]) -
Устаревший псевдоним для
collections.abc.ByteString.Используйте
isinstance(obj, collections.abc.Buffer), чтобы во время выполнения проверить, реализует лиobjбуферный протокол. В аннотациях типов используйте либоBuffer, либо объединение типов с явным перечислением типов, поддерживаемых вашим кодом (например,bytes | bytearray | memoryview).Изначально
ByteStringзадумывался как абстрактный класс, который служил бы суперклассом дляbytesиbytearray. Однако, поскольку у этого ABC никогда не было методов, знание о том, что объект является экземпляромByteString, на самом деле ничего полезного об объекте не сообщало. Другие распространённые буферные типы, такие какmemoryview, также никогда не считались подтипамиByteString(ни во время выполнения, ни средствами статической проверки типов).Дополнительные сведения см. в PEP 688.
Устарело начиная с версии 3.9; будет удалено в версии 3.17.
-
class typing.Collection(Sized, Iterable[T_co], Container[T_co]) -
Устаревший псевдоним для
collections.abc.Collection.Добавлено в версии 3.6.
Устарело начиная с версии 3.9:
collections.abc.Collectionтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Container(Generic[T_co]) -
Устаревший псевдоним для
collections.abc.Container.Устарело начиная с версии 3.9:
collections.abc.Containerтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]]) -
Устаревший псевдоним для
collections.abc.ItemsView.Устарело начиная с версии 3.9:
collections.abc.ItemsViewтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.KeysView(MappingView, AbstractSet[KT_co]) -
Устаревший псевдоним для
collections.abc.KeysView.Устарело начиная с версии 3.9:
collections.abc.KeysViewтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Mapping(Collection[KT], Generic[KT, VT_co]) -
Устаревший псевдоним для
collections.abc.Mapping.Устарело начиная с версии 3.9:
collections.abc.Mappingтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.MappingView(Sized) -
Устаревший псевдоним для
collections.abc.MappingView.Устарело начиная с версии 3.9:
collections.abc.MappingViewтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.MutableMapping(Mapping[KT, VT]) -
Устаревший псевдоним для
collections.abc.MutableMapping.Устарело начиная с версии 3.9:
collections.abc.MutableMappingтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.MutableSequence(Sequence[T]) -
Устаревший псевдоним для
collections.abc.MutableSequence.Устарело начиная с версии 3.9:
collections.abc.MutableSequenceтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.MutableSet(AbstractSet[T]) -
Устаревший псевдоним для
collections.abc.MutableSet.Устарело начиная с версии 3.9:
collections.abc.MutableSetтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.Sequence(Reversible[T_co], Collection[T_co]) -
Устаревший псевдоним для
collections.abc.Sequence.Устарело начиная с версии 3.9:
collections.abc.Sequenceтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
-
class typing.ValuesView(MappingView, Collection[_VT_co]) -
Устаревший псевдоним для
collections.abc.ValuesView.Устарело начиная с версии 3.9:
collections.abc.ValuesViewтеперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.
Псевдонимы асинхронных ABC в collections.abc
-
class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType]) -
Устаревший псевдоним для
collections.abc.Coroutine.Подробные сведения об использовании
collections.abc.Coroutineиtyping.Coroutineв аннотациях типов см. в разделе Аннотирование генераторов и сопрограмм.Добавлено в версии 3.5.3.
Устарело с версии 3.9:
collections.abc.Coroutineтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.
-
class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType]) -
Устаревший псевдоним для
collections.abc.AsyncGenerator.Подробные сведения об использовании
collections.abc.AsyncGeneratorиtyping.AsyncGeneratorв аннотациях типов см. в разделе Аннотирование генераторов и сопрограмм.Добавлено в версии 3.6.1.
Устарело с версии 3.9:
collections.abc.AsyncGeneratorтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.Изменено в версии 3.13: Параметр
SendTypeтеперь имеет значение по умолчанию.
-
class typing.AsyncIterable(Generic[T_co]) -
Устаревший псевдоним для
collections.abc.AsyncIterable.Добавлено в версии 3.5.2.
Устарело с версии 3.9:
collections.abc.AsyncIterableтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.
-
class typing.AsyncIterator(AsyncIterable[T_co]) -
Устаревший псевдоним для
collections.abc.AsyncIterator.Добавлено в версии 3.5.2.
Устарело с версии 3.9:
collections.abc.AsyncIteratorтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.
-
class typing.Awaitable(Generic[T_co]) -
Устаревший псевдоним для
collections.abc.Awaitable.Добавлено в версии 3.5.2.
Устарело с версии 3.9:
collections.abc.Awaitableтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.
Псевдонимы других ABC в 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.Подробные сведения об использовании
collections.abc.Generatorиtyping.Generatorв аннотациях типов см. в разделе Аннотирование генераторов и сопрограмм.Устарело с версии 3.9:
collections.abc.Generatorтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.Изменено в версии 3.13: Добавлены значения по умолчанию для типов отправки и возврата.
-
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.
Псевдонимы ABC из contextlib
-
class typing.ContextManager(Generic[T_co, ExitT_co]) -
Устаревший псевдоним для
contextlib.AbstractContextManager.Первый параметр типа,
T_co, обозначает тип, возвращаемый методом__enter__(). Необязательный второй параметр типа,ExitT_co, значение которого по умолчанию равноbool | None, обозначает тип, возвращаемый методом__exit__().Добавлено в версии 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__().Добавлено в версии 3.6.2.
Устарело с версии 3.9:
contextlib.AbstractAsyncContextManagerтеперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.Изменено в версии 3.13: Добавлен необязательный второй параметр типа,
AExitT_co.
Сроки устаревания основных возможностей
Некоторые возможности в typing объявлены устаревшими и могут быть удалены в будущей версии Python. Для удобства в следующей таблице приведены основные сведения об устаревании. Эта информация может измениться, и в списке указаны не все устаревшие возможности.
Возможность | Устарела в версии | Предполагаемое удаление | PEP/issue |
|---|---|---|---|
| 3.9 | Не определено (дополнительные сведения см. в разделе Устаревшие псевдонимы) | |
3.9 | 3.17 | ||
3.11 | Не определено | ||
3.12 | Не определено | ||
3.12 | Не определено | ||
3.13 | 3.15 | ||
3.13 | 3.18 |
© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/typing.html