Spec-Zone.ru › Python 3.12

typing — Поддержка подсказок типов

Добавлена в версии 3.5.

Исходный код: Lib/typing.py

Примечание

Интерпретатор Python не проверяет типы функций и переменных. Они могут использоваться сторонними инструментами, такими как проверяющие типы, IDE, линтеры и т. д.

Этот модуль предоставляет поддержку подсказок типов во время выполнения.

Рассмотрим функцию ниже:

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)

Вы по-прежнему можете выполнять все int операции с переменной типа UserId, но результат всегда будет типа int. Это позволяет передавать UserId туда, где ожидается int, но предотвратит случайное создание UserId неверным способом:

# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)

Обратите внимание, что эти проверки выполняются только статическим проверяющим типом. Во время выполнения оператор Derived = NewType('Derived', Base) сделает Derived вызываемым объектом, который немедленно возвращает переданный ему параметр. Это означает, что выражение Derived(some_value) не создаёт новый класс и не вносит значительной дополнительной нагрузки помимо обычного вызова функции.

Более точно, выражение some_value is Derived(some_value) всегда истинно во время выполнения.

Недопустимо создавать подтип Derived:

from typing import NewType

UserId = NewType('UserId', int)

# Fails at runtime and does not pass type checking
class AdminUserId(UserId): pass

Однако можно создать NewType на основе «производного» NewType:

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

и проверка типов для ProUserId будет работать как ожидается.

См. PEP 484 для получения дополнительной информации.

Примечание

Помните, что использование псевдонима типа объявляет два типа эквивалентными друг другу. Выполнение type Alias = Original заставит статический проверяющий тип рассматривать Alias как точно эквивалентный Original во всех случаях. Это полезно, когда вы хотите упростить сложные сигнатуры типов.

В отличие от этого, NewType объявляет один тип как подтип другого. Выполнение Derived = NewType('Derived', Original) заставит статический проверяющий тип рассматривать Derived как подкласс Original, что означает, что значение типа Original не может быть использовано там, где ожидается значение типа Derived. Это полезно, когда вы хотите предотвратить логические ошибки с минимальной стоимостью во время выполнения.

Добавлена в версии 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.

Пользовательские обобщенные типы

Пользовательский класс может быть определен как обобщенный класс.

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 для получения дополнительной информации.

Пользовательский обобщенный класс может иметь ABC в качестве базовых классов без конфликтов метаклассов. Обобщенные метаклассы не поддерживаются. Результат параметризации обобщений кэшируется, а большинство типов в модуле 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. Например, это соответствует 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, пользователь может определять новые пользовательские протоколы, чтобы полностью использовать структурную типизацию (см. примеры ниже).

END_OF_DOCUMENT_MARKER

Содержание модуля

Модуль typing определяет следующие классы, функции и декораторы.

Специальные примитивы типизации

Специальные типы

Их можно использовать в качестве типов в аннотациях. Они не поддерживают подписку с использованием [].

typing.Any

Специальный тип, обозначающий не ограниченный тип.

  • Каждый тип совместим с Any.
  • 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!"
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.12: TypeAlias устарело в пользу оператора type, который создаёт экземпляры TypeAliasType и который нативно поддерживает вперёд объявления. Обратите внимание, что, хотя TypeAlias и TypeAliasType служат похожим целям и имеют аналогичные имена, они различны, и последний не является типом первого. Удаление TypeAlias в настоящее время не планируется, но пользователям рекомендуется перейти к операторам type.

Специальные формы

Эти формы могут быть использованы в качестве типов в аннотациях. Все они поддерживают подписку с использованием [], но каждая имеет уникальный синтаксис.

typing.Union

Тип объединения; Union[X, Y] эквивалентно X | Y и означает либо X, либо Y.

Для определения объединения используйте, например, Union[int, str] или сокращенную запись int | str. Использование сокращенной записи рекомендуется. Подробности:

  • Аргументы должны быть типами, и их должно быть по крайней мере один.
  • Объединения объединений сжимаются, например:

    Union[Union[int, str], float] == Union[int, str, float]
    
  • Объединения с одним аргументом исчезают, например:

    Union[int] == int  # The constructor actually returns int
    
  • Избыточные аргументы пропускаются, например:

    Union[int, str, int] == Union[int, str] == int | str
    
  • При сравнении объединений порядок аргументов игнорируется, например:

    Union[int, str] == Union[str, int]
    
  • Вы не можете наследоваться от или создавать экземпляры Union.
  • Вы не можете записать Union[X][Y].

Изменено в версии 3.7: Явных подклассов из объединений не удаляется во время выполнения.

Изменено в версии 3.10: Теперь объединения могут быть записаны как X | Y. См. выражения типа объединения.

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
  • Аннотирование вызываемых объектов
typing.Literal

Специальная форма типизации для определения «литеральных типов».

Literal может использоваться для указания проверкам типов, что аннотированный объект имеет значение, эквивалентное одному из предоставленных литералов.

Например:

def validate_simple(data: Any) -> Literal[True]:  # always returns True
    ...

type Mode = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: Mode) -> str:
    ...

open_helper('/some/path', 'r')      # Passes type check
open_helper('/other/path', 'typo')  # Error in type checker

Literal[...] не может быть подклассом. Во время выполнения любое значение разрешается в качестве аргумента типа для Literal[...], но проверки типов могут накладывать ограничения. См. PEP 586 для получения дополнительной информации о литеральных типах.

Добавлен в версии 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 variable

ClassVar принимает только типы и не может быть далее подписываемым.

ClassVar не является классом сам по себе и не должен использоваться с isinstance() или issubclass(). ClassVar не изменяет поведение Python во время выполнения, но может использоваться сторонними проверками типов. Например, проверка типов может отметить следующий код как ошибку:

enterprise_d = Starship(3000)
enterprise_d.stats = {} # Error, setting class variable on instance
Starship.stats = {}     # This is OK

Добавлен в версии 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=False TypedDicts. См. TypedDict и PEP 655 для получения дополнительной информации.

Добавлен в версии 3.11.

typing.NotRequired

Специальный конструктор типа для маркировки ключа TypedDict как потенциально отсутствующего.

См. TypedDict и PEP 655 для получения дополнительной информации.

Добавлен в версии 3.11.

typing.Annotated

Специальная форма типизации для добавления метаданных, специфичных для контекста, к аннотации.

Добавьте метаданные x к заданному типу T с помощью аннотации Annotated[T, x]. Метаданные, добавленные с помощью Annotated, могут использоваться инструментами статического анализа или во время выполнения. Во время выполнения метаданные хранятся в атрибуте __metadata__.

Если библиотека или инструмент сталкивается с аннотацией Annotated[T, x] и не имеет специальной логики для метаданных, она должна игнорировать метаданные и просто обрабатывать аннотацию как T. Таким образом, Annotated может быть полезным для кода, который хочет использовать аннотации для целей, выходящих за рамки системы статической типизации Python.

Использование Annotated[T, x] в качестве аннотации все еще позволяет выполнять статическую проверку типов T, так как инструменты проверки типов просто проигнорируют метаданные x. Таким образом, Annotated отличается от декоратора @no_type_check, который также может использоваться для добавления аннотаций за пределами системы типизации, но полностью отключает проверку типов для функции или класса.

Ответственность за интерпретацию метаданных лежит на инструменте или библиотеке, столкнувшейся с аннотацией Annotated . Инструмент или библиотека, столкнувшись с типом Annotated, может просматривать элементы метаданных, чтобы определить, представляют ли они интерес (например, используя isinstance()).

Annotated[<type>, <metadata>]

Вот пример того, как можно использовать Annotated для добавления метаданных к аннотациям типов, если вы выполняете анализ диапазонов:

@dataclass
class ValueRange:
    lo: int
    hi: int

T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]

Подробности синтаксиса:

  • Первый аргумент для Annotated должен быть допустимым типом
  • Можно предоставить несколько элементов метаданных (Annotated поддерживает аргументы переменной длины):

    @dataclass
    class ctype:
        kind: str
    
    Annotated[int, ValueRange(3, 10), ctype("char")]
    

    Инструменту, потребляющему аннотации, решать, разрешено ли клиенту добавлять несколько элементов метаданных к одной аннотации и как объединять эти аннотации.

  • Annotated должен быть с индексами как минимум из двух аргументов (Annotated[int] недействительно)
  • Порядок элементов метаданных сохраняется и имеет значение для проверок на равенство:

    assert Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[
        int, ctype("char"), ValueRange(3, 10)
    ]
    
  • Вложенные типы Annotated сглаживаются. Порядок элементов метаданных начинается с самой внутренней аннотации:

    assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
        int, ValueRange(3, 10), ctype("char")
    ]
    
  • Дублированные элементы метаданных не удаляются:

    assert Annotated[int, ValueRange(3, 10)] != Annotated[
        int, ValueRange(3, 10), ValueRange(3, 10)
    ]
    
  • Annotated может использоваться с вложенными и обобщенными псевдонимами:

    @dataclass
    class MaxLen:
        value: int
    
    type Vec[T] = Annotated[list[tuple[T, T]], MaxLen(10)]
    
    # When used in a type annotation, a type checker will treat "V" the same as
    # ``Annotated[list[tuple[int, int]], MaxLen(10)]``:
    type V = Vec[int]
    
  • Annotated нельзя использовать с распакованным TypeVarTuple:

    type Variadic[*Ts] = Annotated[*Ts, Ann1]  # NOT valid
    

    Это эквивалентно:

    Annotated[T1, T2, T3, ..., Ann1]
    

    где T1, T2, и т. д. являются TypeVars. Это будет недопустимо: в Annotated должен быть передан только один тип.

  • По умолчанию get_type_hints() удаляет метаданные из аннотаций. Передайте include_extras=True для сохранения метаданных:

    >>> from typing import Annotated, get_type_hints
    >>> def func(x: Annotated[int, "metadata"]) -> None: pass
    ...
    >>> get_type_hints(func)
    {'x': <class 'int'>, 'return': <class 'NoneType'>}
    >>> get_type_hints(func, include_extras=True)
    {'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>}
    
  • Во время выполнения метаданные, связанные с типом Annotated, могут быть получены через атрибут __metadata__:

    >>> from typing import Annotated
    >>> X = Annotated[int, "very", "important", "metadata"]
    >>> X
    typing.Annotated[int, 'very', 'important', 'metadata']
    >>> X.__metadata__
    ('very', 'important', 'metadata')
    

См. также

PEP 593 - Гибкие аннотации функций и переменных

PEP, который вводит Annotated в стандартную библиотеку.

Добавлен в версии 3.9.

typing.TypeGuard

Специальная конструкция типизации для маркировки пользовательских функций-предикатов типа.

TypeGuard может использоваться для аннотации возвращаемого типа пользовательской функции-предиката типа. TypeGuard принимает только один аргумент типа. Во время выполнения функции, помеченные таким образом, должны возвращать булево значение.

TypeGuard призван принести пользу сужению типов — технике, используемой инструментами статической типизации для определения более точного типа выражения в потоке кода программы. Обычно сужение типов выполняется путем анализа условного потока кода и применения сужения к блоку кода. Условное выражение в этом случае иногда называется «предикатом типа»:

def is_str(val: str | float):
    # "isinstance" type guard
    if isinstance(val, str):
        # Type of ``val`` is narrowed to ``str``
        ...
    else:
        # Else, type of ``val`` is narrowed to ``float``.
        ...

Иногда бывает удобно использовать пользовательскую булеву функцию в качестве предиката типа. Такая функция должна использовать TypeGuard[...] в качестве типа возвращаемого значения, чтобы сообщить инструментам статической типизации об этом намерении.

Использование -> TypeGuard сообщает инструменту статической типизации, что для данной функции:

  1. Возвращаемое значение — булево.
  2. Если возвращаемое значение — True, тип его аргумента — тип внутри TypeGuard.

Например:

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!")

Если is_str_list — метод класса или экземпляра, то тип в TypeGuard соответствует типу второго параметра (после cls или self).

Короче говоря, форма def foo(arg: TypeA) -> TypeGuard[TypeB]: ..., означает, что если foo(arg) возвращает True, то arg сужается от TypeA до TypeB.

Примечание

TypeB не обязательно должен быть более узкой формой TypeA — он может быть даже более широкой. Основная причина заключается в том, чтобы разрешить такие вещи, как сужение list[object] до list[str] даже если последнее не является подтипом первого, так как list инвариантен. Ответственность за написание безопасных с точки зрения типов предикатов типа возлагается на пользователя.

TypeGuard также работает с переменными типов. См. PEP 647 для получения дополнительных сведений.

Добавлен в версии 3.10.

typing.Unpack

Оператор типизации для концептуальной маркировки объекта как распакованного.

Например, использование оператора распаковки * на кортеже переменной типа эквивалентно использованию Unpack для обозначения кортежа переменной типа как распакованного:

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts]
# Effectively does:
tup: tuple[Unpack[Ts]]

На самом деле, Unpack может использоваться взаимозаменяемо с * в контексте typing.TypeVarTuple и builtins.tuple типов. Вы можете увидеть Unpack в явном виде в более ранних версиях Python, где * нельзя было использовать в определенных местах:

# In older versions of Python, TypeVarTuple and Unpack
# are located in the `typing_extensions` backports package.
from typing_extensions import TypeVarTuple, Unpack

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts]         # Syntax error on Python <= 3.10!
tup: tuple[Unpack[Ts]]  # Semantically equivalent, and backwards-compatible

Unpack также можно использовать вместе с typing.TypedDict для типизации **kwargs в сигнатуре функции:

from typing import TypedDict, Unpack

class Movie(TypedDict):
    name: str
    year: int

# This function expects two keyword arguments - `name` of type `str`
# and `year` of type `int`.
def foo(**kwargs: Unpack[Movie]): ...

См. PEP 692 для получения более подробной информации об использовании Unpack для типизации **kwargs.

Добавлен в версии 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)

Переменная типа.

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

class Sequence[T]:  # T is a TypeVar
    ...

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

class StrSequence[S: str]:  # S is a TypeVar bound to str
    ...


class StrOrBytesSequence[A: (str, bytes)]:  # A is a TypeVar constrained to str or bytes
    ...

Однако, если это необходимо, повторно используемые переменные типа также можно создать вручную, как показано ниже:

T = TypeVar('T')  # Can be anything
S = TypeVar('S', bound=str)  # Can be any subtype of str
A = TypeVar('A', str, bytes)  # Must be exactly str or bytes

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

def repeat[T](x: T, n: int) -> Sequence[T]:
    """Return a list containing n references to x."""
    return [x]*n


def print_capitalized[S: str](x: S) -> S:
    """Print x capitalized, and return x."""
    print(x.capitalize())
    return x


def concatenate[A: (str, bytes)](x: A, y: A) -> A:
    """Add two strings or bytes objects together."""
    return x + y

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

Изменчивость переменных типа определяется проверяющими типами при их создании с помощью синтаксиса параметров типа или при передаче infer_variance=True. Вручную созданные переменные типа могут быть явно отмечены как ковариантные или контравариантные путем передачи covariant=True или contravariant=True. По умолчанию вручную созданные переменные типа являются инвариантными. См. PEP 484 и PEP 695 для получения более подробной информации.

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

x = print_capitalized('a string')
reveal_type(x)  # revealed type is str

class StringSubclass(str):
    pass

y = print_capitalized(StringSubclass('another string'))
reveal_type(y)  # revealed type is StringSubclass

z = print_capitalized(45)  # error: int is not a subtype of str

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

# Can be anything with an __abs__ method
def print_abs[T: SupportsAbs](arg: T) -> None:
    print("Absolute value:", abs(arg))

U = TypeVar('U', bound=str|bytes)  # Can be any subtype of the union str|bytes
V = TypeVar('V', bound=SupportsAbs)  # Can be anything with an __abs__ method

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

a = concatenate('one', 'two')
reveal_type(a)  # revealed type is str

b = concatenate(StringSubclass('one'), StringSubclass('two'))
reveal_type(b)  # revealed type is str, despite StringSubclass being passed in

c = concatenate('one', b'two')  # error: type variable 'A' can be either str or bytes in a function call, but not both

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

__name__

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

__covariant__

Указывает, была ли переменная типа явно помечена как ковариантная.

__contravariant__

Указывает, была ли переменная типа явно помечена как контравариантная.

__infer_variance__

Указывает, следует ли проверяющим типов выводить изменчивость переменной типа.

Добавлен в версии 3.12.

__bound__

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

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

__constraints__

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

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

Изменено в версии 3.12: Теперь переменные типа можно объявлять с помощью синтаксиса параметра типа, введенного в PEP 695. Добавлено параметр infer_variance.

class typing.TypeVarTuple(name)

Кортеж переменных типа. Специализированная форма переменной типа, которая позволяет создавать переменные обобщения.

Кортежи переменных типа могут быть объявлены в списках параметров типа с использованием одиночного символа звездочки (*) перед именем:

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__

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

Добавлен в версии 3.11.

Изменено в версии 3.12: Кортежи переменных типа теперь можно объявлять с использованием синтаксиса параметра типа, введенного в PEP 695.

class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False)

Переменная спецификации параметра. Специализированная версия переменных типов.

В списках параметров типа спецификации параметров могут быть объявлены с двумя звёздочками (**):

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]. Однако это вызывает две проблемы:

  1. Инструмент проверки типов не может проверить функцию inner, потому что *args и **kwargs должны быть типизированы как Any.
  2. cast() может потребоваться в теле декоратора add_logging при возвращении функции inner, или инструменту статической проверки типов нужно сказать игнорировать return inner.
args
kwargs

Поскольку ParamSpec захватывает как позиционные, так и ключевые параметры, P.args и P.kwargs могут быть использованы для разделения ParamSpec на компоненты. P.args представляет собой кортеж позиционных параметров в данном вызове и должен использоваться только для аннотации *args. P.kwargs представляет собой отображение ключевых параметров и их значений в данном вызове и должно использоваться только для аннотации **kwargs. Оба атрибута требуют, чтобы аннотируемый параметр был в области видимости. Во время выполнения, P.args и P.kwargs являются соответственно экземплярами ParamSpecArgs и ParamSpecKwargs.

__name__

Имя спецификации параметра.

Переменные спецификации параметров, созданные с помощью covariant=True или contravariant=True могут быть использованы для объявления ковариативных или контравариативных обобщенных типов. Также принимается аргумент bound, аналогично TypeVar. Однако фактическая семантика этих ключевых слов ещё не определена.

Добавлен в версии 3.10.

Изменено в версии 3.12: Спецификации параметров теперь можно объявлять с использованием синтаксиса параметра типа, введённого в PEP 695.

Примечание

Только переменные спецификации параметров, определённые в глобальной области, могут быть сериализованы.

См. также

  • 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, оба из которых являются частью API namedtuple().)

NamedTuple подклассы также могут иметь строки документации и методы:

class Employee(NamedTuple):
    """Represents an employee."""
    name: str
    id: int = 3

    def __repr__(self) -> str:
        return f'<Employee {self.name}, id={self.id}>'

NamedTuple подклассы могут быть обобщёнными:

class Group[T](NamedTuple):
    key: T
    group: list[T]

Обратно совместимое использование:

# For creating a generic NamedTuple on Python 3.11 or lower
class Group(NamedTuple, Generic[T]):
    key: T
    group: list[T]

# A functional syntax is also supported
Employee = NamedTuple('Employee', [('name', str), ('id', int)])

Изменено в версии 3.6: Добавлена поддержка синтаксиса аннотаций переменных PEP 526.

Изменено в версии 3.6.1: Добавлена поддержка значений по умолчанию, методов и строк документации.

Изменено в версии 3.8: Атрибуты _field_types и __annotations__ теперь являются обычными словарями вместо экземпляров OrderedDict.

Изменено в версии 3.9: Удалён атрибут _field_types в пользу более стандартного атрибута __annotations__ , содержащего ту же информацию.

Изменено в версии 3.11: Добавлена поддержка обобщённых кортежей с именованными полями.

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() (описаны ниже), действуют как простые протоколы времени выполнения, которые проверяют только наличие заданных атрибутов, игнорируя их сигнатуры типов.

Протокольные классы могут быть обобщёнными, например:

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(). Это вызывает TypeError при применении к классу, не являющемуся протоколом. Это позволяет выполнить простую структурную проверку, очень похожую на «хитрости» в collections.abc, такие как Iterable. Например:

@runtime_checkable
class Closable(Protocol):
    def close(self): ...

assert isinstance(open('/some/file'), Closable)

@runtime_checkable
class Named(Protocol):
    name: str

import threading
assert isinstance(threading.Thread(name='Bob'), Named)

Примечание

runtime_checkable() будет проверять только наличие необходимых методов или атрибутов, а не их сигнатуры типов или типы. Например, ssl.SSLObject является классом, поэтому он проходит проверку issubclass() по отношению к Callable. Однако метод ssl.SSLObject.__init__ существует только для повышения TypeError с более информативным сообщением, поэтому его нельзя вызвать (инициализировать) ssl.SSLObject.

Примечание

Проверка isinstance() на протоколе времени выполнения может быть неожиданно медленной по сравнению с проверкой isinstance() на классе, не являющимся протоколом. В производительно чувствительном коде рассмотрите использование альтернативных выражений, таких как вызовы hasattr() для структурных проверок.

Добавлен в версии 3.8.

Изменено в версии 3.12: Внутренняя реализация isinstance() проверок на протоколах времени выполнения теперь использует inspect.getattr_static() для поиска атрибутов (ранее использовалась hasattr()). В результате некоторые объекты, которые ранее считались экземплярами протокола времени выполнения, могут больше не считаться таковыми в Python 3.12+, и наоборот. Большинство пользователей, скорее всего, не пострадают от этого изменения.

Изменено в версии 3.12: Члены протокола времени выполнения теперь считаются «замороженными» во время выполнения сразу после создания класса. Модификация атрибутов протокола времени выполнения по-прежнему работает, но не повлияет на проверки 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')

Для возможности использования этой функции со старыми версиями Python, не поддерживающими PEP 526, TypedDict поддерживает две дополнительные эквивалентные синтаксические формы:

  • Использование литерального dict в качестве второго аргумента:

    Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
    
  • Использование именованных аргументов:

    Point2D = TypedDict('Point2D', x=int, y=int, label=str)
    

    Устарело начиная с версии 3.11, будет удалено в версии 3.13: Синтаксис именованных аргументов устарел в версии 3.11 и будет удален в версии 3.13. Он также может не поддерживаться статическими средствами проверки типов.

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

# raises SyntaxError
class Point2D(TypedDict):
    in: int  # 'in' is a keyword
    x-y: int  # name with hyphens

# OK, functional syntax
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})

По умолчанию все ключи должны быть присутствовать в TypedDict. Можно отметить отдельные ключи как необязательные, используя NotRequired:

class Point2D(TypedDict):
    x: int
    y: int
    label: NotRequired[str]

# Alternative syntax
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})

Это означает, что у Point2D TypedDict может быть опущен ключ label.

Также можно помечать все ключи как необязательные по умолчанию, указав полную совокупность False:

class Point2D(TypedDict, total=False):
    x: int
    y: int

# Alternative syntax
Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)

Это означает, что у Point2D TypedDict может быть опущен любой из ключей. Средство проверки типов должно поддерживать только литеральный False или True в качестве значения аргумента total. True — значение по умолчанию, делающее все элементы, определённые в теле класса, обязательными.

Отдельные ключи total=False TypedDict можно помечать как обязательные, используя Required:

class Point2D(TypedDict, total=False):
    x: Required[int]
    y: Required[int]
    label: str

# Alternative syntax
Point2D = TypedDict('Point2D', {
    'x': Required[int],
    'y': Required[int],
    'label': str
}, total=False)

Тип TypedDict может наследоваться от одного или нескольких других типов TypedDict с использованием синтаксиса на основе классов. Использование:

class Point3D(Point2D):
    z: int

Point3D имеет три элемента: x, y и z. Это эквивалентно этому определению:

class Point3D(TypedDict):
    x: int
    y: int
    z: int

TypedDict не может наследоваться от не-TypedDict класса, за исключением Generic. Например:

class X(TypedDict):
    x: int

class Y(TypedDict):
    y: int

class Z(object): pass  # A non-TypedDict class

class XY(X, Y): pass  # OK

class XZ(X, Z): pass  # raises TypeError

TypedDict может быть дженериком:

class Group[T](TypedDict):
    key: T
    group: list[T]

Для создания дженеричного TypedDict совместимого с Python 3.11 или более ранними версиями, явно наследуйте от Generic:

T = TypeVar("T")

class Group(TypedDict, Generic[T]):
    key: T
    group: list[T]

TypedDict можно проинспектировать через словари аннотаций (см. Рекомендации по лучшим практикам аннотаций для получения дополнительной информации об аннотациях лучших практик), __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__ , может не работать должным образом, и значения атрибутов могут быть неверными.

См. PEP 589 для получения дополнительных примеров и подробных правил использования TypedDict.

Добавлена в версии 3.8.

Изменено в версии 3.11: Добавлена поддержка пометки отдельных ключей как Required или NotRequired. См. PEP 655.

Изменено в версии 3.11: Добавлена поддержка дженеричных TypedDict.

Протоколы

Следующие протоколы предоставляются модулем typing. Все они помечены @runtime_checkable.

class typing.SupportsAbs

ABC с одним абстрактным методом __abs__ , ковариативный по типу возвращаемого значения.

class typing.SupportsBytes

ABC с одним абстрактным методом __bytes__.

class typing.SupportsComplex

ABC с одним абстрактным методом __complex__.

class typing.SupportsFloat

ABC с одним абстрактным методом __float__.

class typing.SupportsIndex

ABC с одним абстрактным методом __index__.

Добавлена в версии 3.8.

class typing.SupportsInt

ABC с одним абстрактным методом __int__.

class typing.SupportsRound

ABC с одним абстрактным методом __round__ , ковариативный по типу возвращаемого значения.

ABC для работы с IO

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, и ничего другого.

Во время выполнения это вызывает исключение при вызове.

См. также

Unreachable Code and Exhaustiveness Checking содержит дополнительную информацию о проверке исчерпываемости с помощью статической типизации.

Добавлена в версии 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) – Принимаются произвольные другие ключевые аргументы, чтобы предоставить возможные будущие расширения.

Анализаторы типов распознают следующие необязательные параметры в спецификациях полей:

Распознанные параметры для спецификаций полей

Имя параметра

Описание

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().

@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, функция возвращает словарь, объединяющий аннотации из базовых классов obj с аннотациями, заданными непосредственно для obj. Это делается путём обхода 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
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.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.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.

Этот тип можно использовать следующим образом:

def count_words(text: str) -> Dict[str, int]:
    ...

Устарел начиная с версии 3.9: builtins.dict теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

class typing.List(list, MutableSequence[T])

Устаревший псевдоним для list.

Обратите внимание, что для аннотации аргументов предпочтительнее использовать абстрактный тип коллекции, такой как Sequence или Iterable, а не list или typing.List.

Этот тип может быть использован следующим образом:

def vec2[T: (int, float)](x: T, y: T) -> List[T]:
    return [x, y]

def keep_positives[T: (int, float)](vector: Sequence[T]) -> List[T]:
    return [item for item in vector if item > 0]

Устарел начиная с версии 3.9: builtins.list теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

class typing.Set(set, MutableSet[T])

Устаревший псевдоним для builtins.set.

Обратите внимание, что для аннотации аргументов предпочтительнее использовать абстрактный тип коллекции, такой как AbstractSet, а не set или typing.Set.

Устарел начиная с версии 3.9: builtins.set теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

class typing.FrozenSet(frozenset, AbstractSet[T_co])

Устаревший псевдоним для builtins.frozenset.

Устарел начиная с версии 3.9: builtins.frozenset теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

typing.Tuple

Устаревший псевдоним для tuple.

tuple и Tuple имеют специальное обращение в системе типов; см. Аннотация кортежей для получения более подробной информации.

Устарел начиная с версии 3.9: builtins.tuple теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

class typing.Type(Generic[CT_co])

Устаревший псевдоним для type.

См. Тип объектов классов для получения подробной информации об использовании type или typing.Type в аннотациях типов.

Добавлен в версии 3.5.2.

Устарел начиная с версии 3.9: builtins.type теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

Псевдонимы типов в collections

class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])

Устаревший псевдоним для collections.defaultdict.

Добавлен в версии 3.5.2.

Устарел начиная с версии 3.9: collections.defaultdict теперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима обобщённого типа.

class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])

Устаревший псевдоним для collections.OrderedDict.

Добавлен в версии 3.7.2.

Устарел начиная с версии 3.9: collections.OrderedDict теперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима обобщённого типа.

class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])

Устаревший псевдоним для collections.ChainMap.

Добавлен в версии 3.6.1.

Устарел начиная с версии 3.9: collections.ChainMap теперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима обобщённого типа.

class typing.Counter(collections.Counter, Dict[T, int])

Устаревший псевдоним для collections.Counter.

Добавлен в версии 3.6.1.

Устарел начиная с версии 3.9: collections.Counter теперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима обобщённого типа.

class typing.Deque(deque, MutableSequence[T])

Устаревший псевдоним для collections.deque.

Добавлен в версии 3.6.1.

Устарел начиная с версии 3.9: collections.deque теперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима обобщённого типа.

Псевдонимы других конкретных типов

Устарел начиная с версии 3.8, будет удален в версии 3.13: Пространство имён typing.io устарело и будет удалено. Эти типы следует импортировать напрямую из typing.

class typing.Pattern
class typing.Match

Устаревшие псевдонимы, соответствующие типам возвращаемых значений из re.compile() и re.match().

Эти типы (и соответствующие функции) являются обобщёнными по AnyStr. Pattern могут быть специализированы как Pattern[str] или Pattern[bytes]; Match могут быть специализированы как Match[str] или Match[bytes].

Устарел начиная с версии 3.8, будет удален в версии 3.13: Пространство имён typing.re устарело и будет удалено. Эти типы следует импортировать напрямую из typing.

Устарел начиная с версии 3.9: Классы Pattern и Match из re теперь поддерживают []. См. PEP 585 и Тип псевдонима обобщённого типа.

class typing.Text

Устаревший псевдоним для str.

Text предоставлен для обеспечения совместимости с кодом Python 2: в Python 2 Text является псевдонимом для 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.

Псевдонимы для ABC контейнеров в collections.abc

class typing.AbstractSet(Collection[T_co])

Устаревший псевдоним для collections.abc.Set.

Устарело начиная с версии 3.9: collections.abc.Set теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.ByteString(Sequence[int])

Этот тип представляет типы bytes, bytearray и memoryview байтовых последовательностей.

Устарело начиная с версии 3.9, будет удалено в версии 3.14: Предпочитайте collections.abc.Buffer или объединение, например, bytes | bytearray | memoryview.

class typing.Collection(Sized, Iterable[T_co], Container[T_co])

Устаревший псевдоним для collections.abc.Collection.

Добавлен в версии 3.6.

Устарело начиная с версии 3.9: collections.abc.Collection теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.Container(Generic[T_co])

Устаревший псевдоним для collections.abc.Container.

Устарело начиная с версии 3.9: collections.abc.Container теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]])

Устаревший псевдоним для collections.abc.ItemsView.

Устарело начиная с версии 3.9: collections.abc.ItemsView теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.KeysView(MappingView, AbstractSet[KT_co])

Устаревший псевдоним для collections.abc.KeysView.

Устарело начиная с версии 3.9: collections.abc.KeysView теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.Mapping(Collection[KT], Generic[KT, VT_co])

Устаревший псевдоним для collections.abc.Mapping.

Этот тип может использоваться следующим образом:

def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
    return word_list[word]

Устарело начиная с версии 3.9: collections.abc.Mapping теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.MappingView(Sized)

Устаревший псевдоним для collections.abc.MappingView.

Устарело начиная с версии 3.9: collections.abc.MappingView теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.MutableMapping(Mapping[KT, VT])

Устаревший псевдоним для collections.abc.MutableMapping.

Устарело начиная с версии 3.9: collections.abc.MutableMapping теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.MutableSequence(Sequence[T])

Устаревший псевдоним для collections.abc.MutableSequence.

Устарело начиная с версии 3.9: collections.abc.MutableSequence теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.MutableSet(AbstractSet[T])

Устаревший псевдоним для collections.abc.MutableSet.

Устарело начиная с версии 3.9: collections.abc.MutableSet теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.Sequence(Reversible[T_co], Collection[T_co])

Устаревший псевдоним для collections.abc.Sequence.

Устарело начиная с версии 3.9: collections.abc.Sequence теперь поддерживает индексацию ([]). См. PEP 585 и Тип обобщенного псевдонима.

class typing.ValuesView(MappingView, Collection[_VT_co])

Устаревшее псевдоним для collections.abc.ValuesView.

Устарело начиная с версии 3.9: collections.abc.ValuesView теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

Псевдонимы асинхронных ABC в collections.abc

class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType])

Устаревшее псевдоним для collections.abc.Coroutine.

Изменение вариативности и порядка типов соответствуют тем, что у Generator, например:

from collections.abc import Coroutine
c: Coroutine[list[str], str, int]  # Some coroutine defined elsewhere
x = c.send('hi')                   # Inferred type of 'x' is list[str]
async def bar() -> None:
    y = await c                    # Inferred type of 'y' is int

Добавлен в версии 3.5.3.

Устарело начиная с версии 3.9: collections.abc.Coroutine теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType])

Устаревшее псевдоним для collections.abc.AsyncGenerator.

Асинхронный генератор можно аннотировать обобщённым типом AsyncGenerator[YieldType, SendType]. Например:

async def echo_round() -> AsyncGenerator[int, float]:
    sent = yield 0
    while sent >= 0.0:
        rounded = await round(sent)
        sent = yield rounded

В отличие от обычных генераторов, асинхронные генераторы не могут возвращать значение, поэтому нет параметра типа ReturnType. Как и у Generator, параметр SendType ведет себя контравариантно.

Если ваш генератор будет только выводить значения, установите SendType в None:

async def infinite_stream(start: int) -> AsyncGenerator[int, 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)

Добавлен в версии 3.6.1.

Устарело начиная с версии 3.9: collections.abc.AsyncGenerator теперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.

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.

Генератор можно аннотировать с помощью дженерического типа Generator[YieldType, SendType, ReturnType]. Например:

def echo_round() -> Generator[int, float, str]:
    sent = yield 0
    while sent >= 0:
        sent = yield round(sent)
    return 'Done'

Обратите внимание, что в отличие от многих других дженериков в модуле typing, поведение SendType у Generator контравариантно, а не ковариантно или инвариантно.

Если ваш генератор будет только выдавать значения, установите SendType и ReturnType в None:

def infinite_stream(start: int) -> Generator[int, None, None]:
    while True:
        yield start
        start += 1

В качестве альтернативы, аннотируйте свой генератор, указав возвращаемый тип либо Iterable[YieldType] или Iterator[YieldType]:

def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1

Устарело начиная с версии 3.9: collections.abc.Generator теперь поддерживает индексирование ([]). См. PEP 585 и Тип псевдонима дженерика.

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])

Устаревший псевдоним для contextlib.AbstractContextManager.

Добавлен в версии 3.5.4.

Устарело начиная с версии 3.9: contextlib.AbstractContextManager теперь поддерживает индексирование ([]). См. PEP 585 и Тип псевдонима дженерика.

class typing.AsyncContextManager(Generic[T_co])

Устаревший псевдоним для contextlib.AbstractAsyncContextManager.

Добавлен в версии 3.6.2.

Устарело начиная с версии 3.9: contextlib.AbstractAsyncContextManager теперь поддерживает индексирование ([]). См. PEP 585 и Тип псевдонима дженерика.

График устаревания основных функций

Определенные функции в typing устарели и могут быть удалены в будущей версии Python. В следующей таблице обобщены основные устаревания для вашего удобства. Данные могут быть изменены, и не все устаревания перечислены.

Функция

Устарела в

Прогнозируемое удаление

PEP/запрос

typing.io и typing.re подмодули

3.8

3.13

bpo-38291

typing версии стандартных коллекций

3.9

Не определено (см. Устаревшие псевдонимы для получения дополнительной информации)

PEP 585

typing.ByteString

3.9

3.14

gh-91896

typing.Text

3.11

Не определено

gh-92332

typing.Hashable и typing.Sized

3.12

Не определено

gh-94309

typing.TypeAlias

3.12

Не определено

PEP 695

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/typing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API