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

Added in version 3.5.

Источник: Lib/typing.py

Примечание

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


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

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

def moon_weight(earth_weight: float) -> str:
    return f'On the moon, you would weigh {earth_weight * 0.166} kilograms.'

Функция moon_weight принимает аргумент, который должен быть экземпляром float, на что указывает подсказка тип earth_weight: float. Ожидается, что функция вернет экземпляр str, на что указывает подсказка -> str.

Хотя подсказки типов могут быть простыми классами, такими как float или str, они могут быть и более сложными. Модуль typing предоставляет словарь более сложных подсказок типов.

В модуль typing часто добавляются новые возможности. Пакет typing_extensions обеспечивает обратный перенос этих новых возможностей на старые версии Python.

См.также

«Typing cheat sheet»

Краткий обзор подсказок типов (размещено в документации mypy)

Раздел «Справочник по системе типов» в the mypy docs

Система типизации Python стандартизирована через PEP, поэтому эта ссылка должна быть применима к большинству программ проверки типов Python. (Некоторые части могут быть специфичны для mypy).

«Static Typing with Python»

Документация, не требующая проверки типов, написанная сообществом, в которой подробно описываются возможности системы типов, полезные инструменты, связанные с типизацией, и лучшие практики типизации.

Спецификация системы типов Python

Каноническую, актуальную спецификацию системы типов Python можно найти по адресу «Specification for the Python type system».

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

Псевдоним типа задается с помощью оператора type, который создает экземпляр TypeAliasType. В этом примере Vector и list[float] будут эквивалентно восприниматься статическими программами проверки типов:

type Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

# passes type checking; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])

Псевдонимы типов полезны для упрощения сложных сигнатур типов. Например:

from collections.abc import Sequence

type ConnectionOptions = dict[str, str]
type Address = tuple[str, int]
type Server = tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: Sequence[Server]) -> None:
    ...

# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
        message: str,
        servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:
    ...

Оператор type является новым в Python 3.12. Для обратной совместимости псевдонимы типов также можно создавать с помощью простого присваивания:

Vector = list[float]

Или пометить TypeAlias, чтобы явно указать, что это псевдоним типа, а не обычное присваивание переменной:

from typing import TypeAlias

Vector: TypeAlias = list[float]

NewType

Используйте помощник NewType для создания отдельных типов:

from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

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

def get_user_name(user_id: UserId) -> str:
    ...

# passes type checking
user_a = get_user_name(UserId(42351))

# fails type checking; an int is not a UserId
user_b = get_user_name(-1)

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

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

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

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

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

from typing import NewType

UserId = NewType('UserId', int)

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

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

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

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

Более подробную информацию см. в разделе PEP 484.

Примечание

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

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

Added in version 3.5.2.

Изменено в версии 3.10: NewType теперь является классом, а не функцией. В результате при вызове NewType вместо обычной функции возникают дополнительные затраты времени выполнения.

Изменено в версии 3.11: Производительность вызова NewType была восстановлена до уровня Python 3.9.

Аннотирование вызываемых объектов

Функции - или другие объекты callable - могут быть аннотированы с помощью collections.abc.Callable или typing.Callable. Callable[[int], str] обозначает функцию, которая принимает один параметр типа int и возвращает str.

Например:

from collections.abc import Callable, Awaitable

def feeder(get_next_item: Callable[[], str]) -> None:
    ...  # Body

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    ...  # Body

async def on_update(value: str) -> None:
    ...  # Body

callback: Callable[[str], Awaitable[None]] = on_update

Синтаксис подписки всегда должен использоваться ровно с двумя значениями: списком аргументов и возвращаемым типом. Список аргументов должен быть списком типов, символами ParamSpec, Concatenate или многоточием. Возвращаемый тип должен быть одним типом.

Если в качестве списка аргументов указано буквенное многоточие ..., это означает, что допустим вызываемый модуль с любым произвольным списком параметров:

def concat(x: str, y: str) -> str:
    return x + y

x: Callable[..., str]
x = str     # OK
x = concat  # Also OK

Callable не может выражать сложные сигнатуры, такие как функции, принимающие переменное число аргументов, overloaded functions или функции, имеющие параметры только с ключевыми словами. Однако эти сигнатуры можно выразить, определив класс Protocol с методом __call__():

from collections.abc import Iterable
from typing import Protocol

class Combiner(Protocol):
    def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...

def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
    for item in data:
        ...

def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
    ...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
    ...

batch_proc([], good_cb)  # OK
batch_proc([], bad_cb)   # Error! Argument 2 has incompatible type because of
                         # different name and kind in the callback

Вызываемые модули, принимающие в качестве аргументов другие вызываемые модули, могут указать, что типы их параметров зависят друг от друга, используя оператор ParamSpec. Кроме того, если вызываемая переменная добавляет или удаляет аргументы из других вызываемых переменных, можно использовать оператор Concatenate. Они имеют форму Callable[ParamSpecVariable, ReturnType] и Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType] соответственно.

Изменено в версии 3.10: Callable теперь поддерживает ParamSpec и Concatenate. Более подробную информацию см. в разделе PEP 612.

См.также

В документации к ParamSpec и Concatenate приведены примеры использования в Callable.

Дженерики

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

from collections.abc import Mapping, Sequence

class Employee: ...

# Sequence[Employee] indicates that all elements in the sequence
# must be instances of "Employee".
# Mapping[str, str] indicates that all keys and all values in the mapping
# must be strings.
def notify_by_email(employees: Sequence[Employee],
                    overrides: Mapping[str, str]) -> None: ...

Общие функции и классы можно параметризовать с помощью type parameter syntax:

from collections.abc import Sequence

def first[T](l: Sequence[T]) -> T:  # Function is generic over the TypeVar "T"
    return l[0]

Или используя фабрику TypeVar напрямую:

from collections.abc import Sequence
from typing import TypeVar

U = TypeVar('U')                  # Declare type variable "U"

def second(l: Sequence[U]) -> U:  # Function is generic over the TypeVar "U"
    return l[1]

Изменено в версии 3.12: В Python 3.12 появилась синтаксическая поддержка дженериков.

Аннотирование кортежей

Для большинства контейнеров в Python система типизации предполагает, что все элементы в контейнере будут иметь один и тот же тип. Например:

from collections.abc import Mapping

# Type checker will infer that all elements in ``x`` are meant to be ints
x: list[int] = []

# Type checker error: ``list`` only accepts a single type argument:
y: list[int, str] = [1, 'foo']

# Type checker will infer that all keys in ``z`` are meant to be strings,
# and that all values in ``z`` are meant to be either strings or ints
z: Mapping[str, str | int] = {}

list принимает только один аргумент типа, поэтому программа проверки типов выдаст ошибку на приведенном выше присваивании y. Аналогично, Mapping принимает только два аргумента типа: первый указывает на тип ключей, а второй - на тип значений.

Однако, в отличие от большинства других контейнеров Python, в идиоматическом коде Python кортежи часто содержат элементы, которые не все имеют одинаковый тип. По этой причине кортежи имеют особый тип в системе типизации Python. tuple принимает любое количество аргументов типа:

# OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int
x: tuple[int] = (5,)

# OK: ``y`` is assigned to a tuple of length 2;
# element 1 is an int, element 2 is a str
y: tuple[int, str] = (5, "foo")

# Error: the type annotation indicates a tuple of length 1,
# but ``z`` has been assigned to a tuple of length 3
z: tuple[int] = (1, 2, 3)

Для обозначения кортежа, который может быть любой длины, и в котором все элементы имеют одинаковый тип T, используйте tuple[T, ...]. Для обозначения пустого кортежа используйте tuple[()]. Использование простого tuple в качестве аннотации эквивалентно использованию tuple[Any, ...]:

x: tuple[int, ...] = (1, 2)
# These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
x = (1, 2, 3)
x = ()
# This reassignment is an error: all elements in ``x`` must be ints
x = ("foo", "bar")

# ``y`` can only ever be assigned to an empty tuple
y: tuple[()] = ()

z: tuple = ("foo", "bar")
# These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
z = (1, 2, 3)
z = ()

Тип объектов класса

Переменная, аннотированная C, может принимать значение типа C. Напротив, переменная, аннотированная type[C] (или typing.Type[C]), может принимать значения, которые сами являются классами - в частности, она будет принимать классовый объект типа C. Например:

a = 3         # Has type ``int``
b = int       # Has type ``type[int]``
c = type(a)   # Also has type ``type[int]``

Обратите внимание, что type[C] ковариантен:

class User: ...
class ProUser(User): ...
class TeamUser(User): ...

def make_new_user(user_class: type[User]) -> User:
    # ...
    return user_class()

make_new_user(User)      # OK
make_new_user(ProUser)   # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser)  # Still fine
make_new_user(User())    # Error: expected ``type[User]`` but got ``User``
make_new_user(int)       # Error: ``type[int]`` is not a subtype of ``type[User]``

Единственными допустимыми параметрами для type являются классы, Any, type variables и объединения любого из этих типов. Например:

def new_non_team_user(user_class: type[BasicUser | ProUser]): ...

new_non_team_user(BasicUser)  # OK
new_non_team_user(ProUser)    # OK
new_non_team_user(TeamUser)   # Error: ``type[TeamUser]`` is not a subtype
                              # of ``type[BasicUser | ProUser]``
new_non_team_user(User)       # Also an error

type[Any] эквивалентен type, который является корнем из metaclass hierarchy в Python.

Определяемые пользователем общие типы

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

from logging import Logger

class LoggedVar[T]:
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value

    def set(self, new: T) -> None:
        self.log('Set ' + repr(self.value))
        self.value = new

    def get(self) -> T:
        self.log('Get ' + repr(self.value))
        return self.value

    def log(self, message: str) -> None:
        self.logger.info('%s: %s', self.name, message)

Этот синтаксис указывает на то, что класс LoggedVar параметризован вокруг единственного type variable T . Это также делает T допустимым типом в теле класса.

Родовые классы неявно наследуют от Generic. Для совместимости с Python 3.11 и ниже, можно также явно наследовать от Generic, чтобы указать на общий класс:

from typing import TypeVar, Generic

T = TypeVar('T')

class LoggedVar(Generic[T]):
    ...

У общих классов есть методы __class_getitem__(), то есть они могут быть параметризованы во время выполнения (например, LoggedVar[int] ниже):

from collections.abc import Iterable

def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
    for var in vars:
        var.set(0)

Родовой тип может иметь любое количество переменных типа. В качестве параметров общего типа допустимы все разновидности TypeVar:

from typing import TypeVar, Generic, Sequence

class WeirdTrio[T, B: Sequence[bytes], S: (int, str)]:
    ...

OldT = TypeVar('OldT', contravariant=True)
OldB = TypeVar('OldB', bound=Sequence[bytes], covariant=True)
OldS = TypeVar('OldS', int, str)

class OldWeirdTrio(Generic[OldT, OldB, OldS]):
    ...

Каждый аргумент переменной типа в Generic должен быть отдельным. Таким образом, это неверно:

from typing import TypeVar, Generic
...

class Pair[M, M]:  # SyntaxError
    ...

T = TypeVar('T')

class Pair(Generic[T, T]):   # INVALID
    ...

Общие классы также могут наследоваться от других классов:

from collections.abc import Sized

class LinkedList[T](Sized):
    ...

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

from collections.abc import Mapping

class MyDict[T](Mapping[str, T]):
    ...

В данном случае MyDict имеет единственный параметр, T.

Использование родового класса без указания параметров типа предполагает наличие Any для каждой позиции. В следующем примере MyIterable не является родовым, но неявно наследуется от Iterable[Any]:

from collections.abc import Iterable

class MyIterable(Iterable): # Same as Iterable[Any]
    ...

Также поддерживаются псевдонимы общих типов, определяемые пользователем. Примеры:

from collections.abc import Iterable

type Response[S] = Iterable[S] | int

# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
    ...

type Vec[T] = Iterable[tuple[T, T]]

def inproduct[T: (int, float, complex)](v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
    return sum(x*y for x, y in v)

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

from collections.abc import Iterable
from typing import TypeVar

S = TypeVar("S")
Response = Iterable[S] | int

Изменено в версии 3.7: У Generic больше нет пользовательского метакласса.

Изменено в версии 3.12: В версии 3.12 появилась синтаксическая поддержка дженериков и псевдонимов типов. Ранее родовые классы должны были явно наследоваться от Generic или содержать переменную типа в одной из своих основ.

Определяемые пользователем родословные для выражений параметров также поддерживаются через переменные спецификации параметров в форме [**P]. Поведение соответствует описанному выше поведению переменных типов, поскольку переменные спецификации параметров рассматриваются модулем типизации как специализированные переменные типов. Единственным исключением из этого является то, что список типов может быть использован для замены ParamSpec:

>>> class Z[T, **P]: ...  # T is a TypeVar; P is a ParamSpec
...
>>> Z[int, [dict, float]]
__main__.Z[int, [dict, float]]

Классы, общие для ParamSpec, также могут быть созданы с помощью явного наследования от Generic. В этом случае ** не используется:

from typing import ParamSpec, Generic

P = ParamSpec('P')

class Z(Generic[P]):
    ...

Еще одно различие между TypeVar и ParamSpec заключается в том, что дженерик с одной переменной спецификации параметров будет принимать списки параметров в форме X[[Type1, Type2, ...]], а также X[Type1, Type2, ...] по эстетическим соображениям. Внутри языка последняя форма преобразуется в первую, так что следующие варианты эквивалентны:

>>> class X[**P]: ...
...
>>> X[int, str]
__main__.X[[int, str]]
>>> X[[int, str]]
__main__.X[[int, str]]

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

Изменено в версии 3.10: Generic теперь можно параметризовать через выражения параметров. Более подробную информацию см. в разделах ParamSpec и PEP 612.

Определенный пользователем общий класс может иметь ABC в качестве базового класса без конфликта с метаклассом. Родовые метаклассы не поддерживаются. Результат параметризации дженериков кэшируется, а большинство типов в модуле типизации являются hashable и сравнимы по равенству.

Тип Any

Особым типом является Any. Статическая программа проверки типов будет рассматривать каждый тип как совместимый с Any, а Any - как совместимый с любым типом.

Это означает, что над значением типа Any можно выполнить любую операцию или вызов метода и присвоить его любой переменной:

from typing import Any

a: Any = None
a = []          # OK
a = 2           # OK

s: str = ''
s = a           # OK

def foo(item: Any) -> int:
    # Passes type checking; 'item' could be any type,
    # and that type might have a 'bar' method
    item.bar()
    ...

Обратите внимание, что при присвоении значения типа Any более точному типу проверка типов не выполняется. Например, статическая проверка типов не сообщила об ошибке при присвоении a типу s, хотя s был объявлен как тип str и во время выполнения получает значение int!

Кроме того, все функции без возвращаемого типа или типов параметров будут неявно использовать по умолчанию Any:

def legacy_parser(text):
    ...
    return data

# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
    ...
    return data

Такое поведение позволяет использовать Any в качестве эскейп-люка, когда вам нужно смешать динамически и статически типизированный код.

Противопоставьте поведение Any поведению object. Как и в Any, каждый тип является подтипом object. Однако, в отличие от Any, обратное не верно: object не является подтипом любого другого типа.

Это означает, что если тип значения object, программа проверки типов отвергнет почти все операции над ним, а присвоение переменной (или использование ее в качестве возвращаемого значения) более специализированного типа будет ошибкой типа. Например:

def hash_a(item: object) -> int:
    # Fails type checking; an object does not have a 'magic' method.
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Passes type checking
    item.magic()
    ...

# Passes type checking, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")

# Passes type checking, since Any is compatible with all types
hash_b(42)
hash_b("foo")

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

Номинальная и структурная подтипизация

Изначально PEP 484 определил систему статических типов Python как использующую номинальную подтипизацию. Это означает, что класс A разрешен там, где ожидается класс B, тогда и только тогда, когда A является подклассом B.

Ранее это требование распространялось и на абстрактные базовые классы, такие как Iterable. Проблема с этим подходом заключалась в том, что класс должен был быть явно помечен для их поддержки, что непитонично и не похоже на то, что обычно делается в идиоматическом динамически типизированном коде Python. Например, это соответствует PEP 484:

from collections.abc import Sized, Iterable, Iterator

class Bucket(Sized, Iterable[int]):
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

PEP 544 позволяет решить эту проблему, позволяя пользователям писать приведенный выше код без явных базовых классов в определении класса, что позволяет Bucket неявно считаться подтипом и Sized, и Iterable[int] при статической проверке типов. Это известно как структурная подтипизация (или статическая утиная подтипизация):

from collections.abc import Iterator, Iterable

class Bucket:  # Note: no base classes
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket())  # Passes type check

Более того, подклассифицировав специальный класс Protocol, пользователь может определить новые пользовательские протоколы, чтобы в полной мере использовать структурную подтипизацию (см. примеры ниже).

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

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

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

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

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

typing.Any

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

  • Каждый тип совместим с Any.

  • Any совместим с любым типом.

Изменено в версии 3.11: Any теперь можно использовать в качестве базового класса. Это может быть полезно для избежания ошибок проверки типов в классах, которые могут «уткать» тип в любом месте или являются очень динамичными.

typing.AnyStr

A constrained type variable.

Определение:

AnyStr = TypeVar('AnyStr', str, bytes)

AnyStr предназначен для функций, которые могут принимать аргументы str или bytes, но не могут позволить им смешиваться.

Например:

def concat(a: AnyStr, b: AnyStr) -> AnyStr:
    return a + b

concat("foo", "bar")    # OK, output has type 'str'
concat(b"foo", b"bar")  # OK, output has type 'bytes'
concat("foo", b"bar")   # Error, cannot mix str and bytes

Обратите внимание, что, несмотря на свое название, AnyStr не имеет ничего общего с типом Any и не означает «любая строка». В частности, AnyStr и str | bytes отличаются друг от друга и имеют разные случаи использования:

# Invalid use of AnyStr:
# The type variable is used only once in the function signature,
# so cannot be "solved" by the type checker
def greet_bad(cond: bool) -> AnyStr:
    return "hi there!" if cond else b"greetings!"

# The better way of annotating this function:
def greet_proper(cond: bool) -> str | bytes:
    return "hi there!" if cond else b"greetings!"

Утратил актуальность с версии 3.13, будет удален в версии 3.18: Утратил актуальность в пользу нового type parameter syntax. Используйте class A[T: (str, bytes)]: ... вместо импорта AnyStr. См. PEP 695 для более подробной информации.

В Python 3.16 AnyStr будет удален из typing.__all__, а при обращении к typing или его импорте во время выполнения будут выдаваться предупреждения об устаревании. В Python 3.18 AnyStr будет удален из typing.

typing.LiteralString

Специальный тип, включающий только литеральные строки.

Любой строковый литерал совместим с LiteralString, так же как и другой LiteralString. Однако объект, типизированный как просто str, не совместим. Строка, созданная путем объединения объектов, типизированных как LiteralString, также допустима как LiteralString.

Пример:

def run_query(sql: LiteralString) -> None:
    ...

def caller(arbitrary_string: str, literal_string: LiteralString) -> None:
    run_query("SELECT * FROM students")  # OK
    run_query(literal_string)  # OK
    run_query("SELECT * FROM " + literal_string)  # OK
    run_query(arbitrary_string)  # type checker error
    run_query(  # type checker error
        f"SELECT * FROM students WHERE name = {arbitrary_string}"
    )

LiteralString полезен для чувствительных API, где произвольные строки, созданные пользователем, могут вызвать проблемы. Например, два вышеприведенных случая, которые генерируют ошибки проверки типов, могут быть уязвимы для атаки SQL-инъекции.

Более подробную информацию см. в разделе PEP 675.

Added in version 3.11.

typing.Never
typing.NoReturn

Never и NoReturn представляют тип bottom type, у которого нет членов.

Они могут использоваться для указания на то, что функция никогда не возвращается, например sys.exit():

from typing import Never  # or NoReturn

def stop() -> Never:
    raise RuntimeError('no way')

Или определить функцию, которая никогда не должна быть вызвана, поскольку у нее нет допустимых аргументов, например assert_never():

from typing import Never  # or NoReturn

def never_call_me(arg: Never) -> None:
    pass

def int_or_str(arg: int | str) -> None:
    never_call_me(arg)  # type checker error
    match arg:
        case int():
            print("It's an int")
        case str():
            print("It's a str")
        case _:
            never_call_me(arg)  # OK, arg is of type Never (or NoReturn)

Never и NoReturn имеют одинаковое значение в системе типов, и статические программы проверки типов обрабатывают их эквивалентно.

Added in version 3.6.2: Добавлено NoReturn.

Added in version 3.11: Добавлено Never.

typing.Self

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

Например:

from typing import Self, reveal_type

class Foo:
    def return_self(self) -> Self:
        ...
        return self

class SubclassOfFoo(Foo): pass

reveal_type(Foo().return_self())  # Revealed type is "Foo"
reveal_type(SubclassOfFoo().return_self())  # Revealed type is "SubclassOfFoo"

Эта аннотация семантически эквивалентна следующей, хотя и более лаконичной:

from typing import TypeVar

Self = TypeVar("Self", bound="Foo")

class Foo:
    def return_self(self: Self) -> Self:
        ...
        return self

В общем случае, если что-то возвращает self, как в приведенных выше примерах, то в качестве аннотации возврата следует использовать Self. Если бы Foo.return_self был аннотирован как возвращающий "Foo", то программа проверки типов определила бы, что объект, возвращаемый из SubclassOfFoo.return_self, имеет тип Foo, а не SubclassOfFoo.

Другие распространенные варианты использования включают:

  • classmethod, которые используются как альтернативные конструкторы и возвращают экземпляры параметра cls.

  • Аннотация метода __enter__(), который возвращает self.

Не следует использовать Self в качестве аннотации return, если не гарантируется, что метод вернет экземпляр подкласса, когда класс будет подклассифицирован:

class Eggs:
    # Self would be an incorrect return annotation here,
    # as the object returned is always an instance of Eggs,
    # even in subclasses
    def returns_eggs(self) -> "Eggs":
        return Eggs()

Более подробную информацию см. в разделе PEP 673.

Added in version 3.11.

typing.TypeAlias

Специальная аннотация для явного объявления type alias.

Например:

from typing import TypeAlias

Factors: TypeAlias = list[int]

TypeAlias особенно полезен в старых версиях Python для аннотирования псевдонимов, использующих прямые ссылки, поскольку программам проверки типов бывает сложно отличить их от обычных присваиваний переменных:

from typing import Generic, TypeAlias, TypeVar

T = TypeVar("T")

# "Box" does not exist yet,
# so we have to use quotes for the forward reference on Python <3.12.
# Using ``TypeAlias`` tells the type checker that this is a type alias declaration,
# not a variable assignment to a string.
BoxOfStrings: TypeAlias = "Box[str]"

class Box(Generic[T]):
    @classmethod
    def make_box_of_strings(cls) -> BoxOfStrings: ...

Более подробную информацию см. в разделе PEP 613.

Added in version 3.10.

Не рекомендуется, начиная с версии 3.12: Оператор TypeAlias устарел в пользу оператора type, который создает экземпляры TypeAliasType и который изначально поддерживает прямые ссылки. Обратите внимание, что хотя операторы TypeAlias и TypeAliasType служат схожим целям и имеют похожие имена, они отличаются друг от друга, и последний не является типом первого. Удаление TypeAlias в настоящее время не планируется, но пользователям рекомендуется перейти на операторы type.

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

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

typing.Union

Союзный тип; Union[X, Y] эквивалентен X | Y и означает либо X, либо Y.

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

  • Аргументы должны быть типами, и их должно быть не менее одного.

  • Союзы союзов уплощаются, например:

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

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

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

    Union[int, str] == Union[str, int]
    
  • Вы не можете подклассифицировать или инстанцировать Union.

  • Вы не можете написать Union[X][Y].

Изменено в версии 3.7: Не удаляйте явные подклассы из союзов во время выполнения.

Изменено в версии 3.10: Союзы теперь можно записать в виде X | Y. См. union type expressions.

typing.Optional

Optional[X] эквивалентен X | None (или Union[X, None]).

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

def foo(arg: int = 0) -> None:
    ...

С другой стороны, если допускается явное значение None, уместно использовать Optional, независимо от того, является ли аргумент необязательным или нет. Например:

def foo(arg: Optional[int] = None) -> None:
    ...

Изменено в версии 3.10: Теперь опцию можно записать как X | None. См. union type expressions.

typing.Concatenate

Специальная форма для аннотирования функций высшего порядка.

Concatenate может использоваться в сочетании с Callable и ParamSpec для аннотирования вызываемой переменной более высокого порядка, которая добавляет, удаляет или преобразует параметры другой вызываемой переменной. Используется в форме Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]. В настоящее время Concatenate действителен только при использовании в качестве первого аргумента Callable. Последний параметр Concatenate должен быть ParamSpec или многоточием (...).

Например, для аннотации декоратора with_lock, который предоставляет threading.Lock декорируемой функции, можно использовать Concatenate, чтобы указать, что with_lock ожидает вызываемую функцию, которая принимает Lock в качестве первого аргумента, а возвращает вызываемую функцию с другой сигнатурой типа. В этом случае ParamSpec указывает, что типы параметров возвращаемой вызываемой переменной зависят от типов параметров передаваемой вызываемой переменной:

from collections.abc import Callable
from threading import Lock
from typing import Concatenate

# Use this lock to ensure that only one thread is executing a function
# at any time.
my_lock = Lock()

def with_lock[**P, R](f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]:
    '''A type-safe decorator which provides a lock.'''
    def inner(*args: P.args, **kwargs: P.kwargs) -> R:
        # Provide the lock as the first argument.
        return f(my_lock, *args, **kwargs)
    return inner

@with_lock
def sum_threadsafe(lock: Lock, numbers: list[float]) -> float:
    '''Add a list of numbers together in a thread-safe manner.'''
    with lock:
        return sum(numbers)

# We don't need to pass in the lock ourselves thanks to the decorator.
sum_threadsafe([1.1, 2.2, 3.3])

Added in version 3.10.

См.также

typing.Literal

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

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

Например:

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

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

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

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

Added in version 3.8.

Изменено в версии 3.9.1: Literal теперь не дублирует параметры. Сравнение равенства объектов Literal больше не зависит от порядка. Объекты Literal теперь будут вызывать исключение TypeError при сравнении равенства, если один из их параметров не является hashable.

typing.ClassVar

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

Как было введено в PEP 526, аннотация переменной, обернутая в ClassVar, указывает, что данный атрибут предназначен для использования в качестве переменной класса и не должен устанавливаться для экземпляров этого класса. Использование:

class Starship:
    stats: ClassVar[dict[str, int]] = {} # class variable
    damage: int = 10                     # instance variable

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

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

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

Added in version 3.5.3.

Изменено в версии 3.13: Теперь ClassVar может быть вложен в Final и наоборот.

typing.Final

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

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

Например:

MAX_SIZE: Final = 9000
MAX_SIZE += 1  # Error reported by type checker

class Connection:
    TIMEOUT: Final[int] = 10

class FastConnector(Connection):
    TIMEOUT = 1  # Error reported by type checker

Проверка этих свойств во время выполнения не производится. Более подробную информацию см. в разделе PEP 591.

Added in version 3.8.

Изменено в версии 3.13: Теперь Final может быть вложен в ClassVar и наоборот.

typing.Required

Специальная конструкция для обозначения клавиши TypedDict как необходимой.

В основном это полезно для total=False TypedDicts. Более подробную информацию см. в TypedDict и PEP 655.

Added in version 3.11.

typing.NotRequired

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

Более подробную информацию см. в разделах TypedDict и PEP 655.

Added in version 3.11.

typing.ReadOnly

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

Например:

class Movie(TypedDict):
   title: ReadOnly[str]
   year: int

def mutate_movie(m: Movie) -> None:
   m["year"] = 1992  # allowed
   m["title"] = "The Matrix"  # typechecker error

Это свойство не проверяется во время выполнения.

Более подробную информацию см. в разделах TypedDict и PEP 705.

Added in version 3.13.

typing.Annotated

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

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

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

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

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

Annotated[<type>, <metadata>]

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

@dataclass
class ValueRange:
    lo: int
    hi: int

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

Детали синтаксиса:

  • Первый аргумент Annotated должен быть допустимого типа

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

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

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

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

  • Порядок элементов метаданных сохраняется и имеет значение для проверки равенства:

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

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

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

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

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

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

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

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

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

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

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

См.также

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

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

Added in version 3.9.

typing.TypeIs

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

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

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

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

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

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

  1. Возвращаемое значение - булево.

  2. Если возвращаемое значение равно True, то тип его аргумента равен пересечению исходного типа аргумента и NarrowedType.

  3. Если возвращаемое значение равно False, тип его аргумента сужается, чтобы исключить NarrowedType.

Например:

from typing import assert_type, final, TypeIs

class Parent: pass
class Child(Parent): pass
@final
class Unrelated: pass

def is_parent(val: object) -> TypeIs[Parent]:
    return isinstance(val, Parent)

def run(arg: Child | Unrelated):
    if is_parent(arg):
        # Type of ``arg`` is narrowed to the intersection
        # of ``Parent`` and ``Child``, which is equivalent to
        # ``Child``.
        assert_type(arg, Child)
    else:
        # Type of ``arg`` is narrowed to exclude ``Parent``,
        # so only ``Unrelated`` is left.
        assert_type(arg, Unrelated)

Тип внутри TypeIs должен соответствовать типу аргумента функции; если это не так, статические программы проверки типов выдадут ошибку. Неправильно написанная функция TypeIs может привести к некорректному поведению системы типов; пользователь обязан писать такие функции безопасным для типов образом.

Если функция TypeIs является методом класса или экземпляра, то тип в TypeIs отображается на тип второго параметра после cls или self.

Короче говоря, форма def foo(arg: TypeA) -> TypeIs[TypeB]: ... означает, что если foo(arg) возвращает True, то arg является экземпляром TypeB, а если возвращает False, то не является экземпляром TypeB.

TypeIs также работает с переменными типа. Дополнительные сведения см. в разделе PEP 742 (Сужение типов с помощью TypeIs).

Added in version 3.13.

typing.TypeGuard

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

Функции предиката типа - это определяемые пользователем функции, которые возвращают, является ли их аргумент экземпляром определенного типа. TypeGuard работает так же, как и TypeIs, но оказывает несколько иное влияние на поведение проверки типов (см. ниже).

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

  1. Возвращаемое значение - булево.

  2. Если возвращаемое значение равно True, то тип его аргумента - это тип внутри TypeGuard.

TypeGuard также работает с переменными типа. Более подробную информацию см. в разделе PEP 647.

Например:

def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
    '''Determines whether all objects in the list are strings'''
    return all(isinstance(x, str) for x in val)

def func1(val: list[object]):
    if is_str_list(val):
        # Type of ``val`` is narrowed to ``list[str]``.
        print(" ".join(val))
    else:
        # Type of ``val`` remains as ``list[object]``.
        print("Not a list of strings!")

TypeIs и TypeGuard различаются следующим образом:

  • TypeIs требует, чтобы суженный тип был подтипом входного типа, а TypeGuard - нет. Основная причина - возможность сужения list[object] до list[str], даже если последний не является подтипом первого, поскольку list инвариантен.

  • Когда функция TypeGuard возвращает True, средства проверки типов сужают тип переменной до точного типа TypeGuard. Когда функция TypeIs возвращает True, средства проверки типов могут вывести более точный тип, объединив ранее известный тип переменной с типом TypeIs. (Технически это называется типом пересечения).

  • Когда функция TypeGuard возвращает False, средства проверки типов не могут сузить тип переменной. Когда функция TypeIs возвращает False, средства проверки типов могут сузить тип переменной, чтобы исключить тип TypeIs.

Added in version 3.10.

typing.Unpack

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

Например, использование оператора распаковки * на type variable tuple эквивалентно использованию Unpack, чтобы пометить кортеж переменных типа как распакованный:

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

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

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

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

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

from typing import TypedDict, Unpack

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

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

Подробнее об использовании Unpack для набора **kwargs см. в разделе PEP 692.

Added in version 3.11.

Создание общих типов и псевдонимов типов

Следующие классы не должны использоваться непосредственно в качестве аннотаций. Их предназначение - быть строительными блоками для создания общих типов и псевдонимов типов.

Эти объекты могут быть созданы с помощью специального синтаксиса (оператор:ref:type parameter lists <type-params> и оператор type). Для совместимости с Python 3.11 и более ранними версиями они также могут быть созданы без специального синтаксиса, как описано ниже.

class typing.Generic

Абстрактный базовый класс для общих типов.

Родовой тип обычно объявляется путем добавления списка параметров типа после имени класса:

class Mapping[KT, VT]:
    def __getitem__(self, key: KT) -> VT:
        ...
        # Etc.

Такой класс неявно наследуется от Generic. Семантика этого синтаксиса во время выполнения обсуждается в Language Reference.

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

def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y:
    try:
        return mapping[key]
    except KeyError:
        return default

Здесь скобки после имени функции обозначают generic function.

Для обратной совместимости общие классы также могут быть объявлены путем явного наследования от Generic. В этом случае параметры типа должны быть объявлены отдельно:

KT = TypeVar('KT')
VT = TypeVar('VT')

class Mapping(Generic[KT, VT]):
    def __getitem__(self, key: KT) -> VT:
        ...
        # Etc.
class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)

Тип переменный.

Предпочтительным способом создания переменной типа является специальный синтаксис для generic functions, generic classes и generic type aliases:

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

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

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


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

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

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

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

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


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


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

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

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

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

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

class StringSubclass(str):
    pass

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

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

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

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

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

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

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

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

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

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

__name__

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

__covariant__

Был ли тип var явно помечен как ковариантный.

__contravariant__

Был ли тип var явно помечен как контравариантный.

__infer_variance__

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

Added in version 3.12.

__bound__

Граница переменной типа, если таковая имеется.

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

__constraints__

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

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

__default__

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

Added in version 3.13.

has_default()

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

Added in version 3.13.

Изменено в версии 3.12: Переменные типа теперь можно объявлять, используя синтаксис type parameter, введенный в PEP 695. Был добавлен параметр infer_variance.

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

class typing.TypeVarTuple(name, *, default=typing.NoDefault)

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

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

def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
    return (*tup[1:], tup[0])

Или явно вызвав конструктор TypeVarTuple:

T = TypeVar("T")
Ts = TypeVarTuple("Ts")

def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
    return (*tup[1:], tup[0])

Обычная переменная типа позволяет параметризовать один тип. Кортеж переменной типа, напротив, позволяет параметризовать произвольное количество типов, действуя как произвольное количество переменных типа, обернутых в кортеж. Например:

# T is bound to int, Ts is bound to ()
# Return value is (1,), which has type tuple[int]
move_first_element_to_last(tup=(1,))

# T is bound to int, Ts is bound to (str,)
# Return value is ('spam', 1), which has type tuple[str, int]
move_first_element_to_last(tup=(1, 'spam'))

# T is bound to int, Ts is bound to (str, float)
# Return value is ('spam', 3.0, 1), which has type tuple[str, float, int]
move_first_element_to_last(tup=(1, 'spam', 3.0))

# This fails to type check (and fails at runtime)
# because tuple[()] is not compatible with tuple[T, *Ts]
# (at least one element is required)
move_first_element_to_last(tup=())

Обратите внимание на использование оператора распаковки * в tuple[T, *Ts]. Концептуально, вы можете представить Ts как кортеж переменных типа (T1, T2, ...). Тогда tuple[T, *Ts] станет tuple[T, *(T1, T2, ...)], что эквивалентно tuple[T, T1, T2, ...]. (Обратите внимание, что в старых версиях Python вместо Unpack можно увидеть Unpack[Ts]).

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

x: Ts          # Not valid
x: tuple[Ts]   # Not valid
x: tuple[*Ts]  # The correct way to do it

Кортежи переменных типа могут использоваться в тех же контекстах, что и обычные переменные типа. Например, в определениях классов, аргументов и возвращаемых типов:

class Array[*Shape]:
    def __getitem__(self, key: tuple[*Shape]) -> float: ...
    def __abs__(self) -> "Array[*Shape]": ...
    def get_shape(self) -> tuple[*Shape]: ...

Кортежи переменных типов можно удачно комбинировать с обычными переменными типов:

class Array[DType, *Shape]:  # This is fine
    pass

class Array2[*Shape, DType]:  # This would also be fine
    pass

class Height: ...
class Width: ...

float_array_1d: Array[float, Height] = Array()     # Totally fine
int_array_2d: Array[int, Height, Width] = Array()  # Yup, fine too

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

x: tuple[*Ts, *Ts]            # Not valid
class Array[*Shape, *Shape]:  # Not valid
    pass

Наконец, в качестве аннотации типа *args можно использовать распакованный кортеж переменных типа:

def call_soon[*Ts](
         callback: Callable[[*Ts], None],
         *args: *Ts
) -> None:
    ...
    callback(*args)

В отличие от нераспакованных аннотаций *args - например, *args: int, которые указывают, что все аргументы являются int. - *args: *Ts позволяет ссылаться на типы отдельных аргументов в *args. Здесь это позволяет нам убедиться, что типы *args, переданных в call_soon, соответствуют типам (позиционных) аргументов callback.

Более подробную информацию о кортежах переменных типов см. в разделе PEP 646.

__name__

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

__default__

Значение по умолчанию для кортежа переменных типа, или typing.NoDefault, если значение по умолчанию отсутствует.

Added in version 3.13.

has_default()

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

Added in version 3.13.

Added in version 3.11.

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

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

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

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

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

type IntFunc[**P] = Callable[P, int]

Для совместимости с Python 3.11 и более ранними версиями объекты ParamSpec также могут быть созданы следующим образом:

P = ParamSpec('P')

Переменные спецификации параметров существуют в первую очередь для удобства статической проверки типов. Они используются для передачи типов параметров одного вызываемого объекта другому вызываемому объекту - шаблон, часто встречающийся в функциях более высокого порядка и декораторах. Они действительны только при использовании в Concatenate, или в качестве первого аргумента Callable, или в качестве параметров для пользовательских Generics. Дополнительную информацию о родовых типах см. в Generic.

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

from collections.abc import Callable
import logging

def add_logging[T, **P](f: Callable[P, T]) -> Callable[P, T]:
    '''A type-safe decorator to add logging to a function.'''
    def inner(*args: P.args, **kwargs: P.kwargs) -> T:
        logging.info(f'{f.__name__} was called')
        return f(*args, **kwargs)
    return inner

@add_logging
def add_two(x: float, y: float) -> float:
    '''Add two numbers together.'''
    return x + y

При отсутствии ParamSpec самым простым способом аннотирования было использование TypeVar с привязкой Callable[..., Any]. Однако это приводит к двум проблемам:

  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__

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

__default__

Значение по умолчанию для спецификации параметра, или typing.NoDefault, если значение по умолчанию отсутствует.

Added in version 3.13.

has_default()

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

Added in version 3.13.

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

Added in version 3.10.

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

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

Примечание

Мариновать можно только переменные спецификации параметров, определенные в глобальной области видимости.

См.также

typing.ParamSpecArgs
typing.ParamSpecKwargs

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

Вызов get_origin() на любом из этих объектов вернет исходный ParamSpec:

>>> from typing import ParamSpec, get_origin
>>> P = ParamSpec("P")
>>> get_origin(P.args) is P
True
>>> get_origin(P.kwargs) is P
True

Added in version 3.10.

class typing.TypeAliasType(name, value, *, type_params=())

Тип псевдонимов типов, созданных с помощью оператора type.

Пример:

>>> type Alias = int
>>> type(Alias)
<class 'typing.TypeAliasType'>

Added in version 3.12.

__name__

Имя псевдонима типа:

>>> type Alias = int
>>> Alias.__name__
'Alias'
__module__

Модуль, в котором был определен псевдоним типа:

>>> type Alias = int
>>> Alias.__module__
'__main__'
__type_params__

Параметры типа псевдонима типа, или пустой кортеж, если псевдоним не является общим:

>>> type ListOrSet[T] = list[T] | set[T]
>>> ListOrSet.__type_params__
(T,)
>>> type NotGeneric = int
>>> NotGeneric.__type_params__
()
__value__

Значение псевдонима типа. Это значение lazily evaluated, поэтому имена, используемые в определении псевдонима, не будут разрешены до тех пор, пока не будет получен доступ к атрибуту __value__:

>>> type Mutually = Recursive
>>> type Recursive = Mutually
>>> Mutually
Mutually
>>> Recursive
Recursive
>>> Mutually.__value__
Recursive
>>> Recursive.__value__
Mutually

Другие специальные директивы

Эти функции и классы не должны использоваться непосредственно в качестве аннотаций. Их предназначение - быть строительными блоками для создания и объявления типов.

class typing.NamedTuple

Типизированная версия collections.namedtuple().

Использование:

class Employee(NamedTuple):
    name: str
    id: int

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

Employee = collections.namedtuple('Employee', ['name', 'id'])

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

class Employee(NamedTuple):
    name: str
    id: int = 3

employee = Employee('Guido')
assert employee.id == 3

Поля со значением по умолчанию должны располагаться после полей без значения по умолчанию.

Полученный класс имеет дополнительный атрибут __annotations__, содержащий дикту, которая сопоставляет имена полей с их типами. (Имена полей находятся в атрибуте _fields, а значения по умолчанию - в атрибуте _field_defaults, оба из которых являются частью namedtuple(). API.)

NamedTuple У подклассов также могут быть документы и методы:

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

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

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

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

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

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

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

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

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Недокументированный синтаксис аргумента ключевого слова для создания классов NamedTuple (NT = NamedTuple("NT", x=int)) является устаревшим и будет запрещен в версии 3.15. Вместо этого используйте синтаксис, основанный на классах, или функциональный синтаксис.

Утратил актуальность с версии 3.13, будет удален в версии 3.15: При использовании функционального синтаксиса для создания класса NamedTuple непередача значения параметру „fields“ (NT = NamedTuple("NT")) является устаревшей. Передача None в параметр „fields“ (NT = NamedTuple("NT", None)) также является устаревшей. Оба параметра будут запрещены в Python 3.15. Чтобы создать класс NamedTuple с 0 полями, используйте class NT(NamedTuple): pass или NT = NamedTuple("NT", []).

class typing.NewType(name, tp)

Класс-помощник для создания низкозатратных distinct types.

Проверка типов считает NewType отдельным типом. Однако во время выполнения вызов NewType возвращает его аргумент без изменений.

Использование:

UserId = NewType('UserId', int)  # Declare the NewType "UserId"
first_user = UserId(1)  # "UserId" returns the argument unchanged at runtime
__module__

Модуль, в котором определен новый тип.

__name__

Имя нового типа.

__supertype__

Тип, на котором основан новый тип.

Added in version 3.5.2.

Изменено в версии 3.10: NewType теперь является классом, а не функцией.

class typing.Protocol(Generic)

Базовый класс для классов протоколов.

Классы протоколов определяются следующим образом:

class Proto(Protocol):
    def meth(self) -> int:
        ...

Такие классы в основном используются в статических программах проверки типов, которые распознают структурную подтипизацию (статическая утиная типизация), например:

class C:
    def meth(self) -> int:
        return 0

def func(x: Proto) -> int:
    return x.meth()

func(C())  # Passes static type check

Более подробную информацию см. в разделе PEP 544. Классы протоколов, украшенные runtime_checkable() (описанные позже), действуют как простые протоколы времени выполнения, которые проверяют только наличие заданных атрибутов, игнорируя их сигнатуры типов.

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

class GenProto[T](Protocol):
    def meth(self) -> T:
        ...

В коде, который должен быть совместим с Python 3.11 или старше, общие протоколы могут быть написаны следующим образом:

T = TypeVar("T")

class GenProto(Protocol[T]):
    def meth(self) -> T:
        ...

Added in version 3.8.

@typing.runtime_checkable

Пометить класс протокола как протокол времени выполнения.

Такой протокол можно использовать с isinstance() и issubclass(). Это поднимает TypeError, когда применяется к классу без протокола. Это позволяет выполнить простую структурную проверку, очень похожую на «одноруких пони» в collections.abc, таких как Iterable. Например:

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

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

@runtime_checkable
class Named(Protocol):
    name: str

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

Примечание

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

Примечание

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

Added in version 3.8.

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

Изменено в версии 3.12: Члены протокола, проверяемого временем выполнения, теперь считаются «замороженными» во время выполнения, как только класс был создан. Подстановка атрибутов в протокол, проверяемый во время выполнения, по-прежнему будет работать, но не будет влиять на проверки isinstance(), сравнивающие объекты с протоколом. Более подробную информацию см. в разделе «What’s new in Python 3.12».

class typing.TypedDict(dict)

Специальная конструкция для добавления подсказок типа в словарь. Во время выполнения это обычное dict.

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

class Point2D(TypedDict):
    x: int
    y: int
    label: str

a: Point2D = {'x': 1, 'y': 2, 'label': 'good'}  # OK
b: Point2D = {'z': 3, 'label': 'bad'}           # Fails type check

assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')

Альтернативным способом создания TypedDict является использование синтаксиса вызова функции. Второй аргумент должен быть литералом dict:

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

Этот функциональный синтаксис позволяет определять ключи, которые не являются действительными identifiers, например, потому что они являются ключевыми словами или содержат дефисы:

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

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

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

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

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

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

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

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

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

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

Отдельные клавиши total=False TypedDict могут быть отмечены по мере необходимости с помощью Required:

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

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

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

class Point3D(Point2D):
    z: int

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

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

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

class X(TypedDict):
    x: int

class Y(TypedDict):
    y: int

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

class XY(X, Y): pass  # OK

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

Значение TypedDict может быть общим:

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

Чтобы создать общий TypedDict, совместимый с Python 3.11 или ниже, явно наследуйте от Generic:

T = TypeVar("T")

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

В TypedDict можно интроспектировать с помощью dicts аннотаций (см. Лучшие практики использования аннотаций для получения дополнительной информации о лучших практиках аннотаций), __total__, __required_keys__ и __optional_keys__.

__total__

Point2D.__total__ дает значение аргумента total. Пример:

>>> from typing import TypedDict
>>> class Point2D(TypedDict): pass
>>> Point2D.__total__
True
>>> class Point2D(TypedDict, total=False): pass
>>> Point2D.__total__
False
>>> class Point3D(Point2D): pass
>>> Point3D.__total__
True

Этот атрибут отражает только значение аргумента total для текущего класса TypedDict, а не то, является ли этот класс семантически полным. Например, класс TypedDict с __total__, установленным на True, может иметь ключи, помеченные NotRequired, или наследоваться от другого TypedDict с total=False. Поэтому для интроспекции обычно лучше использовать __required_keys__ и __optional_keys__.

__required_keys__

Added in version 3.9.

__optional_keys__

Point2D.__required_keys__ и Point2D.__optional_keys__ возвращают объекты frozenset, содержащие обязательные и необязательные ключи соответственно.

Клавиши, отмеченные символом Required, всегда будут отображаться в __required_keys__, а клавиши, отмеченные символом NotRequired, всегда будут отображаться в __optional_keys__.

Для обратной совместимости с Python 3.10 и ниже также можно использовать наследование, чтобы объявить требуемые и необязательные ключи в одном и том же TypedDict. Это делается путем объявления TypedDict с одним значением аргумента total, а затем наследования от него в другом TypedDict с другим значением для total:

>>> class Point2D(TypedDict, total=False):
...     x: int
...     y: int
...
>>> class Point3D(Point2D):
...     z: int
...
>>> Point3D.__required_keys__ == frozenset({'z'})
True
>>> Point3D.__optional_keys__ == frozenset({'x', 'y'})
True

Added in version 3.9.

Примечание

Если используется from __future__ import annotations или аннотации заданы в виде строк, аннотации не оцениваются при определении TypedDict. Поэтому интроспекция во время выполнения, на которую опираются __required_keys__ и __optional_keys__, может работать некорректно, а значения атрибутов могут быть неверными.

Поддержка ReadOnly отражена в следующих атрибутах:

__readonly_keys__

Строка frozenset, содержащая имена всех ключей, доступных только для чтения. Ключи доступны только для чтения, если они содержат квалификатор ReadOnly.

Added in version 3.13.

__mutable_keys__

Строка frozenset, содержащая имена всех изменяемых ключей. Ключи являются изменяемыми, если они не содержат квалификатора ReadOnly.

Added in version 3.13.

Примеры и подробные правила использования TypedDict см. в разделе PEP 589.

Added in version 3.8.

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

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

Изменено в версии 3.13: Удалена поддержка метода ключевого слова-аргумента для создания TypedDicts.

Изменено в версии 3.13: Добавлена поддержка квалификатора ReadOnly.

Утратил актуальность с версии 3.13, будет удален в версии 3.15: При использовании функционального синтаксиса для создания класса TypedDict непередача значения параметру „fields“ (TD = TypedDict("TD")) является устаревшей. Передача None в параметр „fields“ (TD = TypedDict("TD", None)) также является устаревшей. Оба параметра будут запрещены в Python 3.15. Чтобы создать класс TypedDict с 0 полями, используйте class TD(TypedDict): pass или TD = TypedDict("TD", {}).

Протоколы

Модуль типизации предоставляет следующие протоколы. Все они украшены символом @runtime_checkable.

class typing.SupportsAbs

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

class typing.SupportsBytes

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

class typing.SupportsComplex

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

class typing.SupportsFloat

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

class typing.SupportsIndex

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

Added in version 3.8.

class typing.SupportsInt

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

class typing.SupportsRound

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

Азбука работы с IO

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)

Added in version 3.11.

typing.assert_never(arg, /)

Попросите программу проверки статических типов подтвердить, что строка кода недостижима.

Пример:

def int_or_str(arg: int | str) -> None:
    match arg:
        case int():
            print("It's an int")
        case str():
            print("It's a str")
        case _ as unreachable:
            assert_never(unreachable)

Здесь аннотации позволяют программе проверки типов сделать вывод, что последний случай никогда не может быть выполнен, поскольку arg является либо int, либо str, и оба варианта покрываются предыдущими случаями.

Если программа проверки типов обнаружит, что вызов assert_never() достижим, она выдаст ошибку. Например, если в аннотации типа для arg вместо int | str | float, программа проверки типов выдаст ошибку, указывая, что unreachable имеет тип float. Чтобы вызов assert_never прошел проверку типов, предполагаемый тип передаваемого аргумента должен быть нижним типом, Never, и ничем другим.

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

См.также

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

Added in version 3.11.

typing.reveal_type(obj, /)

Попросите статическую программу проверки типов определить предполагаемый тип выражения.

Когда программа проверки статических типов встречает вызов этой функции, она выдает диагностику с предполагаемым типом аргумента. Например:

x: int = 1
reveal_type(x)  # Revealed type is "builtins.int"

Это может быть полезно, когда вы хотите отладить, как ваша программа проверки типов обрабатывает определенный фрагмент кода.

Во время выполнения эта функция выводит тип аргумента в sys.stderr и возвращает аргумент без изменений (что позволяет использовать вызов в выражении):

x = reveal_type(1)  # prints "Runtime type is int"
print(x)  # prints "1"

Обратите внимание, что тип во время выполнения может отличаться от типа, статически выведенного программой проверки типов (более или менее определенного).

Большинство программ проверки типов поддерживают reveal_type() в любом месте, даже если имя не импортировано из typing. Импорт имени из typing, однако, позволяет вашему коду работать без ошибок во время выполнения и более четко передает намерения.

Added in version 3.11.

@typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)

Декоратор для маркировки объекта как обеспечивающего dataclass-подобное поведение.

dataclass_transform может использоваться для декорирования класса, метакласса или функции, которая сама является декоратором. Наличие @dataclass_transform() сообщает статической программе проверки типов, что декорированный объект выполняет «магию» во время выполнения, которая преобразует класс подобно @dataclasses.dataclass.

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

@dataclass_transform()
def create_model[T](cls: type[T]) -> type[T]:
    ...
    return cls

@create_model
class CustomerModel:
    id: int
    name: str

На базовом классе:

@dataclass_transform()
class ModelBase: ...

class CustomerModel(ModelBase):
    id: int
    name: str

На метаклассе:

@dataclass_transform()
class ModelMeta(type): ...

class ModelBase(metaclass=ModelMeta): ...

class CustomerModel(ModelBase):
    id: int
    name: str

Классы CustomerModel, определенные выше, будут обрабатываться программами проверки типов так же, как и классы, созданные с помощью @dataclasses.dataclass. Например, программы проверки типов будут считать, что у этих классов есть методы __init__, которые принимают id и name.

Декорируемый класс, метакласс или функция могут принимать следующие bool-аргументы, которые, как предполагают специалисты по проверке типов, имеют тот же эффект, что и в декораторе @dataclasses.dataclass: init, eq, order, unsafe_hash, frozen, match_args, kw_only и slots. Значение этих аргументов (True или False) должно быть статически вычислено.

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

Параметры:
  • eq_default (bool) – Указывает, будет ли параметр eq приниматься за True или False, если он опущен вызывающей стороной. По умолчанию принимается значение True.

  • order_default (bool) – Указывает, будет ли параметр order приниматься за True или False, если он опущен вызывающей стороной. По умолчанию принимается значение False.

  • kw_only_default (bool) – Указывает, будет ли параметр kw_only приниматься за True или False, если он опущен вызывающей стороной. По умолчанию принимается значение False.

  • frozen_default (bool) – Указывает, будет ли параметр frozen приниматься за True или False, если он опущен вызывающей стороной. По умолчанию False. … versionadded:: 3.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.

Added in version 3.11.

@typing.overload

Декоратор для создания перегруженных функций и методов.

Декоратор @overload позволяет описывать функции и методы, поддерживающие несколько различных комбинаций типов аргументов. За серией украшенных @overload-определений должно следовать ровно одно не``@overload``-декорированное определение (для той же функции/метода).

Определения с декорированием @overload``предназначены только для проверки типов, поскольку они будут перезаписаны определением без ``@overload``декорирования. Определение без ``@overload-декорирования, тем временем, будет использоваться во время выполнения, но должно быть проигнорировано программой проверки типов. Во время выполнения вызов @overload-декорированной функции напрямую приведет к появлению NotImplementedError.

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

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    ...  # actual implementation goes here

Более подробную информацию и сравнение с другими семантиками типизации см. в разделе PEP 484.

Изменено в версии 3.11: Перегруженные функции теперь можно интроспектировать во время выполнения с помощью get_overloads().

typing.get_overloads(func)

Возвращает последовательность @overload-декорированных определений для func.

func - это объект функции для реализации перегруженной функции. Например, учитывая определение process в документации к @overload, get_overloads(process) вернет последовательность из трех объектов функций для трех определенных перегрузок. Если вызвать функцию без перегрузок, get_overloads() вернет пустую последовательность.

get_overloads() можно использовать для интроспекции перегруженной функции во время выполнения.

Added in version 3.11.

typing.clear_overloads()

Очистите все зарегистрированные перегрузки во внутреннем реестре.

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

Added in version 3.11.

@typing.final

Декоратор для указания финальных методов и финальных классов.

Украшение метода символом @final указывает программе проверки типов, что этот метод не может быть переопределен в подклассе. Украшение класса символом @final указывает на то, что он не может быть подклассом.

Например:

class Base:
    @final
    def done(self) -> None:
        ...
class Sub(Base):
    def done(self) -> None:  # Error reported by type checker
        ...

@final
class Leaf:
    ...
class Other(Leaf):  # Error reported by type checker
    ...

Проверка этих свойств во время выполнения не производится. Более подробную информацию см. в разделе PEP 591.

Added in version 3.8.

Изменено в версии 3.11: Теперь декоратор попытается установить атрибут __final__ в значение True на декорируемом объекте. Таким образом, проверка типа if getattr(obj, "__final__", False) может быть использована во время выполнения для определения того, был ли объект obj помечен как final. Если декорируемый объект не поддерживает установку атрибутов, декоратор возвращает объект без изменений, не вызывая исключения.

@typing.no_type_check

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

Это работает как с классом, так и с функцией decorator. Для класса он применяется рекурсивно ко всем методам и классам, определенным в этом классе (но не к методам, определенным в его суперклассах или подклассах). Средства проверки типов будут игнорировать все аннотации в функции или классе с этим декоратором.

@no_type_check мутирует украшенный объект на месте.

@typing.no_type_check_decorator

Декоратор для придания другому декоратору эффекта no_type_check().

Это обернет декоратор чем-то, что обернет декорируемую функцию в no_type_check().

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Ни одна программа проверки типов никогда не добавляла поддержку @no_type_check_decorator. Поэтому оно устарело и будет удалено в Python 3.15.

@typing.override

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

Программы проверки типов должны выдавать ошибку, если метод, украшенный символом @override, на самом деле ничего не переопределяет. Это поможет предотвратить ошибки, которые могут возникнуть при изменении базового класса без эквивалентного изменения дочернего класса.

Например:

class Base:
    def log_status(self) -> None:
        ...

class Sub(Base):
    @override
    def log_status(self) -> None:  # Okay: overrides Base.log_status
        ...

    @override
    def done(self) -> None:  # Error reported by type checker
        ...

Проверка этого свойства во время выполнения не предусмотрена.

Декоратор попытается установить атрибут __override__ в значение True на декорируемом объекте. Таким образом, проверка типа if getattr(obj, "__override__", False) может быть использована во время выполнения для определения того, был ли объект obj помечен как переопределение. Если декорируемый объект не поддерживает установку атрибутов, декоратор возвращает объект без изменений, не вызывая исключения.

Более подробную информацию см. в разделе PEP 698.

Added in version 3.12.

@typing.type_check_only

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

Этот декоратор сам по себе недоступен во время выполнения. В основном он предназначен для пометки классов, определенных в файлах-заглушках типов, если реализация возвращает экземпляр приватного класса:

@type_check_only
class Response:  # private or not available at runtime
    code: int
    def get_header(self, name: str) -> str: ...

def fetch_response() -> Response: ...

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

Помощники интроспекции

typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)

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

Часто это то же самое, что и obj.__annotations__. Кроме того, прямые ссылки, закодированные как строковые литералы, обрабатываются путем их оценки в пространствах имен globals, locals и (если применимо) type parameter. Для класса C возвращается словарь, построенный путем объединения всех __annotations__ вдоль C.__mro__ в обратном порядке.

Функция рекурсивно заменяет все Annotated[T, ...] на T, если только include_extras не установлен на True (см. Annotated для получения дополнительной информации). Например:

class Student(NamedTuple):
    name: Annotated[str, 'some marker']

assert get_type_hints(Student) == {'name': str}
assert get_type_hints(Student, include_extras=False) == {'name': str}
assert get_type_hints(Student, include_extras=True) == {
    'name': Annotated[str, 'some marker']
}

Примечание

get_type_hints() не работает с импортированными type aliases, содержащими прямые ссылки. Включение отложенной оценки аннотаций (PEP 563) может устранить необходимость в большинстве прямых ссылок.

Изменено в версии 3.9: Добавлен параметр include_extras как часть параметра PEP 593. Дополнительные сведения см. в документации по Annotated.

Изменено в версии 3.11: Ранее для аннотаций функций и методов добавлялось значение Optional[t], если по умолчанию было установлено значение None. Теперь аннотация возвращается без изменений.

typing.get_origin(tp)

Получение нерасшифрованной версии типа: для объекта типизации вида X[Y, Z, ...] возвращается X.

Если X является псевдонимом встроенного класса или класса collections, то он будет нормализован к исходному классу. Если X является экземпляром ParamSpecArgs или ParamSpecKwargs, возвращается базовый ParamSpec. Для неподдерживаемых объектов возвращается None.

Примеры:

assert get_origin(str) is None
assert get_origin(Dict[str, int]) is dict
assert get_origin(Union[int, str]) is Union
P = ParamSpec('P')
assert get_origin(P.args) is P
assert get_origin(P.kwargs) is P

Added in version 3.8.

typing.get_args(tp)

Получение аргументов типа со всеми выполненными заменами: для объекта типизации вида X[Y, Z, ...] возвращается (Y, Z, ...).

Если X является объединением или Literal содержится в другом родовом типе, порядок (Y, Z, ...) может отличаться от порядка исходных аргументов [Y, Z, ...] из-за кэширования типов. Возвращает () для неподдерживаемых объектов.

Примеры:

assert get_args(int) == ()
assert get_args(Dict[int, str]) == (int, str)
assert get_args(Union[int, str]) == (int, str)

Added in version 3.8.

typing.get_protocol_members(tp)

Возвращает набор членов, определенных в Protocol.

>>> from typing import Protocol, get_protocol_members
>>> class P(Protocol):
...     def a(self) -> str: ...
...     b: int
>>> get_protocol_members(P) == frozenset({'a', 'b'})
True

Вызывает TypeError для аргументов, которые не являются протоколами.

Added in version 3.13.

typing.is_protocol(tp)

Определите, является ли тип Protocol.

Например:

class P(Protocol):
    def a(self) -> str: ...
    b: int

is_protocol(P)    # => True
is_protocol(int)  # => False

Added in version 3.13.

typing.is_typeddict(tp)

Проверьте, является ли тип типом TypedDict.

Например:

class Film(TypedDict):
    title: str
    year: int

assert is_typeddict(Film)
assert not is_typeddict(list | str)

# TypedDict is a factory for creating typed dicts,
# not a typed dict itself
assert not is_typeddict(TypedDict)

Added in version 3.10.

class typing.ForwardRef

Класс, используемый для внутреннего типового представления прямых ссылок на строки.

Например, List["SomeClass"] неявно преобразуется в List[ForwardRef("SomeClass")]. ForwardRef не должен инстанцироваться пользователем, но может использоваться инструментами интроспекции.

Примечание

Общие типы PEP 585, такие как list["SomeClass"], не будут неявно преобразованы в list[ForwardRef("SomeClass")] и, следовательно, не будут автоматически разрешаться в list[SomeClass].

Added in version 3.7.4.

typing.NoDefault

Объект-дозорный, используемый для указания того, что параметр типа не имеет значения по умолчанию. Например:

>>> T = TypeVar("T")
>>> T.__default__ is typing.NoDefault
True
>>> S = TypeVar("S", default=None)
>>> S.__default__ is None
True

Added in version 3.13.

Постоянно

typing.TYPE_CHECKING

Специальная константа, которая принимается за True сторонними статическими программами проверки типов. Во время выполнения она становится False.

Использование:

if TYPE_CHECKING:
    import expensive_mod

def fun(arg: 'expensive_mod.SomeType') -> None:
    local_var: expensive_mod.AnotherType = other_fun()

Первая аннотация типа должна быть заключена в кавычки, что делает ее «прямой ссылкой», чтобы скрыть ссылку expensive_mod от времени выполнения интерпретатора. Аннотации типов для локальных переменных не оцениваются, поэтому вторую аннотацию не нужно заключать в кавычки.

Примечание

Если используется from __future__ import annotations, аннотации не оцениваются во время определения функции. Вместо этого они хранятся в виде строк в __annotations__. Это делает ненужным использование кавычек вокруг аннотации (см. PEP 563).

Added in version 3.5.2.

Утраченные псевдонимы

Этот модуль определяет несколько устаревших псевдонимов для ранее существовавших классов стандартной библиотеки. Изначально они были включены в модуль типизации для поддержки параметризации этих общих классов с помощью []. Однако в Python 3.9 эти псевдонимы стали излишними, когда соответствующие существующие классы были усовершенствованы для поддержки [] (см. PEP 585).

Лишние типы устарели, начиная с Python 3.9. Однако, хотя псевдонимы могут быть удалены в какой-то момент, в настоящее время удаление этих псевдонимов не планируется. Поэтому в настоящее время интерпретатор не выдает предупреждений об устаревании этих псевдонимов.

Если в какой-то момент будет решено удалить эти устаревшие псевдонимы, интерпретатор будет выдавать предупреждение об устаревании не менее чем за два выпуска до удаления. Псевдонимы гарантированно останутся в модуле типизации без предупреждений об устаревании по крайней мере до Python 3.14.

Программам проверки типов рекомендуется отмечать использование устаревших типов, если проверяемая ими программа использует минимальную версию Python 3.9 или новее.

Псевдонимы для встроенных типов

class typing.Dict(dict, MutableMapping[KT, VT])

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

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

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

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

Не рекомендуется, начиная с версии 3.9: builtins.dict теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

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

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

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

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

Не рекомендуется, начиная с версии 3.9: builtins.list теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

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

Не рекомендуется, начиная с версии 3.9: builtins.set теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Не рекомендуется, начиная с версии 3.9: builtins.frozenset теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

typing.Tuple

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

В системе типов tuple и Tuple имеют особые случаи; подробнее см. в Аннотирование кортежей.

Не рекомендуется, начиная с версии 3.9: builtins.tuple теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.Type(Generic[CT_co])

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

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

Added in version 3.5.2.

Не рекомендуется, начиная с версии 3.9: builtins.type теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

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

Added in version 3.5.2.

Не рекомендуется, начиная с версии 3.9: collections.defaultdict теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Added in version 3.7.2.

Не рекомендуется, начиная с версии 3.9: collections.OrderedDict теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Added in version 3.6.1.

Не рекомендуется, начиная с версии 3.9: collections.ChainMap теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Added in version 3.6.1.

Не рекомендуется, начиная с версии 3.9: collections.Counter теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Added in version 3.6.1.

Не рекомендуется, начиная с версии 3.9: collections.deque теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

class typing.Pattern
class typing.Match

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

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

Не рекомендуется, начиная с версии 3.9: Классы Pattern и Match из re теперь поддерживают []. См. PEP 585 и Общий тип псевдонима.

class typing.Text

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

Text предоставлен для обеспечения совместимого пути для кода Python 2: в Python 2 Text является псевдонимом для unicode.

Используйте Text, чтобы указать, что значение должно содержать строку юникода, совместимую как с Python 2, так и с Python 3:

def add_unicode_checkmark(text: Text) -> Text:
    return text + u' \u2713'

Added in version 3.5.2.

Не рекомендуется, начиная с версии 3.11: Python 2 больше не поддерживается, и большинство программ проверки типов также больше не поддерживают проверку типа кода Python 2. Устранение псевдонима в настоящее время не планируется, но пользователям рекомендуется использовать str вместо Text.

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

class typing.AbstractSet(Collection[T_co])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Set теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Added in version 3.6.

Не рекомендуется, начиная с версии 3.9: collections.abc.Collection теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.Container(Generic[T_co])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Container теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.ItemsView теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.KeysView теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Mapping теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.MappingView(Sized)

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

Не рекомендуется, начиная с версии 3.9: collections.abc.MappingView теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.MutableMapping теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.MutableSequence(Sequence[T])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.MutableSequence теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.MutableSet(AbstractSet[T])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.MutableSet теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Sequence теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.ValuesView теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

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

Дисперсия и порядок переменных типа соответствуют переменным Generator, например:

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

Added in version 3.5.3.

Не рекомендуется, начиная с версии 3.9: collections.abc.Coroutine теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

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

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

Генератор async может быть аннотирован общим типом AsyncGenerator[YieldType, SendType]. Например:

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

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

По умолчанию SendType принимает значение None:

async def infinite_stream(start: int) -> AsyncGenerator[int]:
    while True:
        yield start
        start = await increment(start)

Можно также задать этот тип в явном виде:

async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
    while True:
        yield start
        start = await increment(start)

В качестве альтернативы укажите, что ваш генератор имеет тип возврата либо AsyncIterable[YieldType], либо AsyncIterator[YieldType]:

async def infinite_stream(start: int) -> AsyncIterator[int]:
    while True:
        yield start
        start = await increment(start)

Added in version 3.6.1.

Не рекомендуется, начиная с версии 3.9: collections.abc.AsyncGenerator теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

Изменено в версии 3.13: Параметр SendType теперь имеет значение по умолчанию.

class typing.AsyncIterable(Generic[T_co])

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

Added in version 3.5.2.

Не рекомендуется, начиная с версии 3.9: collections.abc.AsyncIterable теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.AsyncIterator(AsyncIterable[T_co])

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

Added in version 3.5.2.

Не рекомендуется, начиная с версии 3.9: collections.abc.AsyncIterator теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.Awaitable(Generic[T_co])

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

Added in version 3.5.2.

Не рекомендуется, начиная с версии 3.9: collections.abc.Awaitable теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

Псевдонимы к другим азбукам в collections.abc

class typing.Iterable(Generic[T_co])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Iterable теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.Iterator(Iterable[T_co])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Iterator теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

typing.Callable

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

О том, как использовать collections.abc.Callable и typing.Callable в аннотациях типов, см. в разделе Аннотирование вызываемых объектов.

Не рекомендуется, начиная с версии 3.9: collections.abc.Callable теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

Изменено в версии 3.10: Callable теперь поддерживает ParamSpec и Concatenate. Более подробную информацию см. в разделе PEP 612.

class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])

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

Генератор может быть аннотирован общим типом Generator[YieldType, SendType, ReturnType]. Например:

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

Обратите внимание, что в отличие от многих других родов в модуле типизации, SendType из Generator ведет себя контравариантно, а не ковариантно или инвариантно.

Параметры SendType и ReturnType по умолчанию равны None:

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

Также можно задать эти типы в явном виде:

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

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

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Generator теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

Изменено в версии 3.13: Добавлены значения по умолчанию для типов send и return.

class typing.Hashable

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

Не рекомендуется, начиная с версии 3.12: Вместо этого используйте collections.abc.Hashable напрямую.

class typing.Reversible(Iterable[T_co])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.Reversible теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

class typing.Sized

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

Не рекомендуется, начиная с версии 3.12: Вместо этого используйте collections.abc.Sized напрямую.

Псевдонимы к contextlib Азбука

class typing.ContextManager(Generic[T_co, ExitT_co])

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

Первый параметр типа, T_co, представляет тип, возвращаемый методом __enter__(). Необязательный второй параметр типа, ExitT_co, который по умолчанию равен bool | None, представляет тип, возвращаемый методом __exit__().

Added in version 3.5.4.

Не рекомендуется, начиная с версии 3.9: contextlib.AbstractContextManager теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

Изменено в версии 3.13: Добавлен необязательный второй параметр типа, ExitT_co.

class typing.AsyncContextManager(Generic[T_co, AExitT_co])

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

Первый параметр типа, T_co, представляет тип, возвращаемый методом __aenter__(). Необязательный второй параметр типа, AExitT_co, который по умолчанию равен bool | None, представляет тип, возвращаемый методом __aexit__().

Added in version 3.6.2.

Не рекомендуется, начиная с версии 3.9: contextlib.AbstractAsyncContextManager теперь поддерживает подписку ([]). См. PEP 585 и Общий тип псевдонима.

Изменено в версии 3.13: Добавлен необязательный второй параметр типа, AExitT_co.

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

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

Характеристика

Утратил актуальность в

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

ПЭП/выпуск

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

3.9

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

PEP 585

typing.Text

3.11

Не определившиеся

gh-92332

typing.Hashable и typing.Sized

3.12

Не определившиеся

gh-94309

typing.TypeAlias

3.12

Не определившиеся

PEP 695

@typing.no_type_check_decorator

3.13

3.15

gh-106309

typing.AnyStr

3.13

3.18

gh-105578