Документация Python неофициальный перевод
Содержание страницы

typing – Поддержка аннотаций типовtyping – Support for type hints

Новое в версии 3.5.

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

Примечание

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


Данный модуль предоставляет поддержку аннотаций типов на уровне выполнения. Самая базовая поддержка включает типы Any, Union, Callable, TypeVar и Generic. Полную спецификацию см. в PEP 484. Для упрощённого введения в аннотации типов см. PEP 483.

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

def greeting(name: str) -> str:
    return 'Hello ' + name

В функции greeting аргумент name ожидается типа str, а возвращаемый тип – str. Подтипы допускаются в качестве аргументов.

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

См. также

Для быстрого ознакомления с аннотациями типов обратитесь к этому краткому справочнику.

Раздел «Справочник по системе типов» из https://mypy.readthedocs.io/ – поскольку система аннотаций Python стандартизирована через PEP, данный справочник должен быть в целом применим к большинству проверяющих типы, хотя некоторые части могут по-прежнему относиться к mypy.

Документация на https://typing.readthedocs.io/ служит полезным справочником по возможностям системы типов, полезным инструментам для аннотаций и лучшим практикам.

Соответствующие PEPRelevant PEPs

С момента первого появления аннотаций типов в PEP 484 и PEP 483 ряд PEP изменил и расширил инфраструктуру Python для аннотаций типов. К ним относятся:

  • PEP 526: Синтаксис аннотаций переменных

    Вводит синтаксис аннотирования переменных вне определений функций, а также ClassVar

  • PEP 544: Протоколы: структурная типизация (статическая утиная типизация)

    Вводит Protocol и декоратор @runtime_checkable

  • PEP 585: Обобщённые типы в стандартных коллекциях

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

  • PEP 586: Литеральные типы

    Представлен Literal

  • PEP 589: TypedDict: аннотации типов для словарей с фиксированным набором ключей

    Представлен TypedDict

  • PEP 591: Добавление квалификатора final в typing

    Вводит Final и декоратор @final

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

    Представлен Annotated

  • PEP 604: Разрешение записи объединённых типов как X | Y

    Вводит types.UnionType и возможность использовать бинарный оператор ИЛИ | для обозначения объединения типов

  • PEP 612: Переменные спецификации параметров

    Представлен ParamSpec и Concatenate

  • PEP 613: Явные псевдонимы типов

    Представлен TypeAlias

  • PEP 647: Защитники типов, определяемые пользователем

    Представлен TypeGuard

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

Псевдоним типа определяется присваиванием типа псевдониму. В этом примере Vector и list[float] будут рассматриваться как взаимозаменяемые синонимы:

Vector = list[float]

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

# проходит проверку типов; список чисел с плавающей точкой считается Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])

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

from collections.abc import Sequence

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

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

# Статическая проверка типов будет считать предыдущую сигнатуру типа как
# полностью эквивалентную этой.
def broadcast_message(
        message: str,
        servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:
    ...

Обратите внимание, что None как аннотация типа является особым случаем и заменяется на type(None).

NewType

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

from typing import NewType

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

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

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

# проходит проверку типов
user_a = get_user_name(UserId(42351))

# не проходит проверку типов; int не является UserId
user_b = get_user_name(-1)

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

# 'output' имеет тип 'int', а не '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)

# Завершается ошибкой во время выполнения и не проходит проверку типов
class AdminUserId(UserId): pass

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

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

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

Подробнее см. PEP 484.

Примечание

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

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

Новое в версии 3.5.2.

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

Callable

Фреймворки, ожидающие функции обратного вызова с определённой сигнатурой, могут быть аннотированы с помощью Callable[[Arg1Type, Arg2Type], ReturnType].

Например:

from collections.abc import Callable

def feeder(get_next_item: Callable[[], str]) -> None:
    # Тело

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    # Тело

async def on_update(value: str) -> None:
    # Тело
callback: Callable[[str], Awaitable[None]] = on_update

Можно объявить возвращаемый тип вызываемого объекта, не указывая сигнатуру вызова, заменив список аргументов многоточием в аннотации типа: Callable[..., ReturnType].

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

Changed in version 3.10: Callable now supports ParamSpec and Concatenate. See PEP 612 for more details.

См. также

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

Обобщённые типыGenerics

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

from collections.abc import Mapping, Sequence

def notify_by_email(employees: Sequence[Employee],
                    overrides: Mapping[str, str]) -> None: ...

Обобщённые типы можно параметризовать с помощью фабрики, доступной в typing под названием TypeVar.

from collections.abc import Sequence
from typing import TypeVar

T = TypeVar('T')      # Объявить переменную типа

def first(l: Sequence[T]) -> T:   # Обобщённая функция
    return l[0]

Пользовательские обобщённые типыUser-defined generic types

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

from typing import TypeVar, Generic
from logging import Logger

T = TypeVar('T')

class LoggedVar(Generic[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)

Generic[T] в качестве базового класса определяет, что класс LoggedVar принимает один параметр типа T. Это также делает T допустимым типом внутри тела класса.

Базовый класс Generic определяет __class_getitem__() так, что LoggedVar[T] является допустимым типом:

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

T = TypeVar('T', contravariant=True)
B = TypeVar('B', bound=Sequence[bytes], covariant=True)
S = TypeVar('S', int, str)

class WeirdTrio(Generic[T, B, S]):
    ...

Каждый аргумент-переменная типа для Generic должен быть уникальным. Поэтому такой код некорректен:

from typing import TypeVar, Generic
...

T = TypeVar('T')

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

Можно использовать множественное наследование с Generic:

from collections.abc import Sized
from typing import TypeVar, Generic

T = TypeVar('T')

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

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

from collections.abc import Mapping
from typing import TypeVar

T = TypeVar('T')

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

В этом случае MyDict имеет один параметр – T.

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

from collections.abc import Iterable

class MyIterable(Iterable): # То же, что и Iterable[Any].

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

from collections.abc import Iterable
from typing import TypeVar
S = TypeVar('S')
Response = Iterable[S] | int

# Тип возвращаемого значения здесь такой же, как Iterable[str] | int
def response(query: str) -> Response[str]:
    ...

T = TypeVar('T', int, float, complex)
Vec = Iterable[tuple[T, T]]

def inproduct(v: Vec[T]) -> T: # То же, что и Iterable[tuple[T, T]]
    return sum(x*y for x, y in v)

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

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

>>> from typing import Generic, ParamSpec, TypeVar

>>> T = TypeVar('T')
>>> P = ParamSpec('P')

>>> class Z(Generic[T, P]): ...
...
>>> Z[int, [dict, float]]
__main__.Z[int, (<class 'dict'>, <class 'float'>)]

Кроме того, обобщённый (generic) с единственной переменной спецификации параметра будет принимать списки параметров в виде X[[Type1, Type2, ...]], а также X[Type1, Type2, ...] из эстетических соображений. Внутренне последний преобразуется в первый, поэтому следующие эквивалентны:

>>> class X(Generic[P]): ...
...
>>> X[int, str]
__main__.X[(<class 'int'>, <class 'str'>)]
>>> X[[int, str]]
__main__.X[(<class 'int'>, <class 'str'>)]

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

Изменено в версии 3.10: Generic теперь можно параметризовать по выражениям параметров. Подробнее см. ParamSpec и PEP 612.

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

Тип AnyThe Any type

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

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

from typing import Any

a: Any = None
a = []          # ОК
a = 2           # ОК

s: str = ''
s = a           # ОК

def foo(item: Any) -> int:
    # Проходит проверку типов; 'item' может быть любого типа,
    # и этот тип может иметь метод 'bar'
    item.bar()
    ...

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

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

def legacy_parser(text):
    ...
    return data

# Статический проверщик типов будет рассматривать вышеприведенное
# как имеющее ту же сигнатуру, что и:
def legacy_parser(text: Any) -> Any:
    ...
    return data

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

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

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

def hash_a(item: object) -> int:
    # Не проходит проверку типов; у объекта нет метода 'magic'.
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Проходит проверку типов
    item.magic()
    ...

# Проходит проверку типов, так как int и str являются подклассами object
hash_a(42)
hash_a("foo")

# Проходит проверку типов, так как Any совместим со всеми типами
hash_b(42)
hash_b("foo")

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

Номинальная и структурная типизацияNominal vs structural subtyping

Изначально 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:  # Примечание: базовые классы отсутствуют
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket())  # Проходит проверку типов

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

Содержимое модуляModule contents

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

Примечание

Данный модуль определяет несколько типов, которые являются подклассами уже существующих классов стандартной библиотеки и которые также расширяют Generic для поддержки переменных типа внутри []. Эти типы стали избыточными в Python 3.9, когда соответствующие существовавшие классы были расширены для поддержки [].

Избыточные типы объявлены устаревшими начиная с Python 3.9, но интерпретатор не будет выдавать предупреждений об устаревании. Ожидается, что средства проверки типов будут помечать устаревшие типы, если проверяемая программа нацелена на Python 3.9 или новее.

Устаревшие типы будут удалены из модуля typing в первой версии Python, выпущенной через 5 лет после выхода Python 3.9.0. Подробнее см. в PEP 585Аннотации обобщённых типов в стандартных коллекциях.

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

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

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

typing.Any

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

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

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

typing.NoReturn

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

from typing import NoReturn

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

Новое в версии 3.5.4.

Новое в версии 3.6.2.

typing.TypeAlias

Специальная аннотация для явного объявления псевдонима типа. Например:

from typing import TypeAlias

Factors: TypeAlias = list[int]

См. PEP 613 для получения дополнительных сведений о явных псевдонимах типов.

Новое в версии 3.10.

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

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

typing.Tuple

Тип кортежа; Tuple[X, Y] – это тип кортежа из двух элементов, где первый элемент имеет тип X, а второй – Y. Тип пустого кортежа может быть записан как Tuple[()].

Пример: Tuple[T1, T2] – это кортеж из двух элементов, соответствующих переменным типа T1 и T2. Tuple[int, float, str] – это кортеж из int, float и строки.

Чтобы задать кортеж переменной длины из однотипных элементов, используйте литеральное многоточие, например Tuple[int, ...]. Простой Tuple эквивалентен Tuple[Any, ...], а тот, в свою очередь, tuple.

Deprecated since version 3.9: builtins.tuple now supports subscripting ([]). See PEP 585 and Generic Alias 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  # Конструктор на самом деле возвращает int
    
  • Повторяющиеся аргументы пропускаются, например:

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

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

  • Нельзя записать Union[X][Y].

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

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

typing.Optional

Тип Optional.

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

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

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

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

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

Изменено в версии 3.10: Optional теперь можно записывать как X | None. См. выражения типов объединений.

typing.Callable

Тип Callable; Callable[[int], str] – это функция вида (int) -> str.

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

Нет синтаксиса для указания необязательных или именованных аргументов; такие типы функций редко используются в качестве типов колбэков. Callable[..., ReturnType] (буквальное многоточие) можно использовать для аннотации вызываемого объекта, принимающего любое количество аргументов и возвращающего ReturnType. Обычное Callable эквивалентно Callable[..., Any], а в свою очередь – collections.abc.Callable.

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

Deprecated since version 3.9: collections.abc.Callable now supports subscripting ([]). See PEP 585 and Generic Alias Type.

Changed in version 3.10: Callable now supports ParamSpec and Concatenate. See PEP 612 for more details.

См. также

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

typing.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, ParamSpec, TypeVar

P = ParamSpec('P')
R = TypeVar('R')

# Используйте эту блокировку, чтобы гарантировать, что только один поток выполняет функцию
# в любой момент времени.
my_lock = Lock()

def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]:
    '''Типобезопасный декоратор, предоставляющий блокировку.'''
    def inner(*args: P.args, **kwargs: P.kwargs) -> R:
        # Передайте блокировку в качестве первого аргумента.
        return f(my_lock, *args, **kwargs)
    return inner

@with_lock
def sum_threadsafe(lock: Lock, numbers: list[float]) -> float:
    '''Складывайте список чисел потокобезопасным способом.'''
    with lock:
        return sum(numbers)

# Нам не нужно передавать блокировку вручную благодаря декоратору.
sum_threadsafe([1.1, 2.2, 3.3])

Новое в версии 3.10.

См. также

  • PEP 612 – переменные спецификации параметров (PEP, который ввёл ParamSpec и Concatenate).

  • ParamSpec и Callable.

class typing.Type(Generic[CT_co])

Переменная, аннотированная C, может принимать значение типа C. Напротив, переменная, аннотированная Type[C], может принимать значения, которые сами являются классами – а именно, она принимает объект класса C. Например:

a = 3         # Имеет тип 'int'
b = int       # Имеет тип 'Type[int]'
c = type(a)   # Также имеет тип 'Type[int]'

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

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

# Принимает User, BasicUser, ProUser, TeamUser, ...
def make_new_user(user_class: Type[User]) -> User:
    # ...
    return user_class()

Тот факт, что Type[C] ковариантен, подразумевает, что все подклассы C должны реализовывать те же сигнатуры конструктора и методов класса, что и C. Средство проверки типов должно отмечать нарушения этого, но также должно разрешать вызовы конструкторов в подклассах, которые соответствуют вызовам конструктора в указанном базовом классе. То, как средство проверки типов должно обрабатывать этот конкретный случай, может измениться в будущих версиях PEP 484.

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

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

Type[Any] эквивалентен Type, который в свою очередь эквивалентен type, корню метаклассовой иерархии Python.

Новое в версии 3.5.2.

Deprecated since version 3.9: builtins.type now supports subscripting ([]). See PEP 585 and Generic Alias Type.

typing.Literal

Тип, который можно использовать для указания средствам проверки типов, что соответствующая переменная или параметр функции имеет значение, эквивалентное предоставленному литералу (или одному из нескольких литералов). Например:

def validate_simple(data: Any) -> Literal[True]:  # всегда возвращает True
    ...

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

open_helper('/some/path', 'r')  # Проходит проверку типов
open_helper('/other/path', 'typo')  # Ошибка в тайпчекере

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

Новое в версии 3.8.

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

typing.ClassVar

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

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

class Starship:
    stats: ClassVar[dict[str, int]] = {} # переменная класса
    damage: int = 10                     # переменная экземпляра

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

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

enterprise_d = Starship(3000)
enterprise_d.stats = {} # Ошибка: установка переменной класса на экземпляре
Starship.stats = {}     # Это корректно.

Новое в версии 3.5.3.

typing.Final

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

MAX_SIZE: Final = 9000
MAX_SIZE += 1  # Ошибка, выдаваемая проверщиком типов

class Connection:
    TIMEOUT: Final[int] = 10

class FastConnector(Connection):
    TIMEOUT = 1  # Ошибка, выдаваемая проверщиком типов

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

Новое в версии 3.8.

typing.Annotated

Тип, введённый в PEP 593 (Flexible function and variable annotations), для декорирования существующих типов контекстно-зависимыми метаданными (возможно, несколькими их частями, так как Annotated вариадичен). В частности, тип T можно аннотировать метаданными x с помощью аннотации типа Annotated[T, x]. Эти метаданные можно использовать как для статического анализа, так и во время выполнения. Если библиотека (или инструмент) встречает аннотацию типа Annotated[T, x] и не имеет специальной логики для метаданных x, она должна игнорировать их и просто обрабатывать тип как T. В отличие от функциональности no_type_check, которая в настоящее время существует в модуле typing и полностью отключает проверку типов аннотаций для функции или класса, тип Annotated позволяет как статическую проверку типов T (которая может безопасно игнорировать x), так и доступ к x во время выполнения в рамках конкретного приложения.

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

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

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

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

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

Передача include_extras=True в get_type_hints() позволяет получить доступ к дополнительным аннотациям во время выполнения.

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

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

  • Поддерживаются несколько аннотаций типов (Annotated поддерживает вариадические аргументы):

    Annotated[int, ValueRange(3, 10), ctype("char")]
    
  • Annotated должен вызываться как минимум с двумя аргументами ( Annotated[int] недействителен)

  • Порядок аннотаций сохраняется и важен для проверки на равенство:

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

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

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

    T = TypeVar('T')
    Vec = Annotated[list[tuple[T, T]], MaxLen(10)]
    V = Vec[int]
    
    V == Annotated[list[tuple[int, int]], MaxLen(10)]
    

Новое в версии 3.9.

typing.TypeGuard

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

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

def is_str(val: str | float):
    # защита типа "isinstance"
    if isinstance(val, str):
        # Тип ``val`` сужается до ``str``
        ...
    else:
        # Иначе тип ``val`` сужается до ``float``.
        ...

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

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

  1. Возвращаемое значение – boolean.

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

Например:

def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
    '''Определяет, все ли объекты в списке являются строками'''
    return all(isinstance(x, str) for x in val)

def func1(val: List[object]):
    if is_str_list(val):
        # Тип ``val`` сужен до ``List[str]``.
        print(" ".join(val))
    else:
        # Тип ``val`` остаётся ``List[object]``.
        print("Not a list of strings!")

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

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

Примечание

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

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

Новое в версии 3.10.

Построение обобщённых типовBuilding generic types

Они не используются в аннотациях. Это строительные блоки для создания обобщённых типов.

class typing.Generic

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

Обобщённый тип обычно объявляется наследованием от экземпляра этого класса с одной или несколькими переменными типа. Например, обобщённый тип отображения может быть определён так:

class Mapping(Generic[KT, VT]):
    def __getitem__(self, key: KT) -> VT:
        ...
        # И т.д.

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

X = TypeVar('X')
Y = TypeVar('Y')

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

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

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

T = TypeVar('T')  # Может быть чем угодно
S = TypeVar('S', bound=str)  # Может быть любым подтипом str
A = TypeVar('A', str, bytes)  # Должно быть ровно str или bytes

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

def repeat(x: T, n: int) -> Sequence[T]:
    """Возвращает список, содержащий n ссылок на x."""
    return [x]*n


def print_capitalized(x: S) -> S:
    """Печатает x с заглавной буквы и возвращает x."""
    print(x.capitalize())
    return x


def concatenate(x: A, y: A) -> A:
    """Складывает две строки или два объекта bytes."""
    return x + y

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

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

a = concatenate('one', 'two')  # Ок, переменная 'a' имеет тип 'str'
b = concatenate(StringSubclass('one'), StringSubclass('two'))  # Выведенный тип переменной 'b' – 'str',
                                                               # несмотря на передачу 'StringSubclass'
c = concatenate('one', b'two')  # ошибка: переменная типа 'A' может быть 'str' или 'bytes' при вызове функции, но не оба сразу

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

print_capitalized('a string')  # Ок, результат имеет тип 'str'

class StringSubclass(str):
    pass

print_capitalized(StringSubclass('another string'))  # Ок, результат имеет тип 'StringSubclass'
print_capitalized(45)  # ошибка: int не является подтипом str

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

U = TypeVar('U', bound=str|bytes)  # Может быть любым подтипом объединения str|bytes
V = TypeVar('V', bound=SupportsAbs)  # Может быть чем угодно с методом __abs__

Связанные переменные типов особенно полезны для аннотации classmethods, которые служат альтернативными конструкторами. В следующем примере (от Рэймонда Хеттингера) переменная типа C привязана к классу Circle через использование прямой ссылки. Использование этой переменной типа для аннотации метода класса with_circumference, а не жёсткого кодирования возвращаемого типа как Circle, означает, что средство проверки типов может правильно вывести возвращаемый тип, даже если метод вызывается на подклассе:

import math

C = TypeVar('C', bound='Circle')

class Circle:
    """Абстрактная окружность"""

    def __init__(self, radius: float) -> None:
        self.radius = radius

    # Используется переменная типа, чтобы показать, что возвращаемый тип
    # всегда будет экземпляром того, чем является ``cls``
    @classmethod
    def with_circumference(cls: type[C], circumference: float) -> C:
        """Создать окружность с указанной длиной окружности"""
        radius = circumference / (math.pi * 2)
        return cls(radius)


class Tire(Circle):
    """Специализированная окружность (из резины)"""

    MATERIAL = 'rubber'


c = Circle.with_circumference(3)  # Ок, переменная 'c' имеет тип 'Circle'
t = Tire.with_circumference(4)  # Ок, переменная 't' имеет тип 'Tire' (не 'Circle')

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

Переменные типа могут быть помечены как ковариантные или контравариантные путём передачи covariant=True или contravariant=True. См. PEP 484 для получения дополнительных сведений. По умолчанию переменные типа инвариантны.

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

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

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

P = ParamSpec('P')

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

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

from collections.abc import Callable
from typing import TypeVar, ParamSpec
import logging

T = TypeVar('T')
P = ParamSpec('P')

def add_logging(f: Callable[P, T]) -> Callable[P, T]:
    '''Типобезопасный декоратор для добавления логирования в функцию.'''
    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:
    '''Складывает два числа.'''
    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.

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

Новое в версии 3.10.

Примечание

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

См. также

  • PEP 612 – Переменные спецификации параметров (PEP, который ввёл ParamSpec и Concatenate).

  • Callable и Concatenate.

typing.ParamSpecArgs
typing.ParamSpecKwargs

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

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

P = ParamSpec("P")
get_origin(P.args)  # возвращает P
get_origin(P.kwargs)  # возвращает P

Новое в версии 3.10.

typing.AnyStr

AnyStr – это constrained type variable, определённый как AnyStr = TypeVar('AnyStr', str, bytes).

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

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

concat(u"foo", u"bar")  # Ок, результат имеет тип 'unicode'
concat(b"foo", b"bar")  # Ок, результат имеет тип 'bytes'
concat(u"foo", b"bar")  # Ошибка, нельзя смешивать unicode и bytes
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())  # Проходит статическую проверку типов

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

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

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

Новое в версии 3.8.

@typing.runtime_checkable

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

Такой протокол может использоваться с isinstance() и issubclass(). При применении к классу, не являющемуся протоколом, возникает TypeError. Это позволяет выполнять простую структурную проверку, очень похожую на “one trick ponies” в collections.abc, таких как Iterable. Например:

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

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

@runtime_checkable
class Named(Protocol):
    name: str

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

Примечание

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

Примечание

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

Новое в версии 3.8.

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

Они не используются в аннотациях. Это строительные блоки для объявления типов.

class typing.NamedTuple

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

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

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

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

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

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

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

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

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

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

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

class Employee(NamedTuple):
    """Представляет сотрудника."""
    name: str
    id: int = 3

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

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

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__, который содержит ту же информацию.

class typing.NewType(name, tp)

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

UserId = NewType('UserId', int)
first_user = UserId(1)

Новое в версии 3.5.2.

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

class typing.TypedDict(dict)

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

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

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

a: Point2D = {'x': 1, 'y': 2, 'label': 'good'}  # ОК
b: Point2D = {'z': 3, 'label': 'bad'}           # Не проходит проверку типов

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

Чтобы разрешить использование этой возможности в старых версиях Python, которые не поддерживают PEP 526, TypedDict поддерживает две дополнительные эквивалентные синтаксические формы:

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

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

# возбуждает SyntaxError
class Point2D(TypedDict):
    in: int  # 'in' – ключевое слово
    x-y: int  # имя с дефисами

# ОК, функциональный синтаксис
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})

По умолчанию все ключи должны присутствовать в TypedDict. Это можно переопределить, указав totality. Использование:

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

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

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  # Класс, не являющийся TypedDict

class XY(X, Y): pass  # ОК

class XZ(X, Z): pass  # вызывает TypeError

T = TypeVar('T')
class XT(X, Generic[T]): pass  # вызывает TypeError

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

__total__

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

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

Новое в версии 3.9.

__optional_keys__

Point2D.__required_keys__ и Point2D.__optional_keys__ возвращают объекты frozenset, содержащие обязательные и необязательные ключи соответственно. В настоящее время единственный способ объявить как обязательные, так и необязательные ключи в одном TypedDict – это смешанное наследование: объявить TypedDict с одним значением для аргумента total, а затем унаследовать его от другого TypedDict с другим значением для total. Использование:

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

Новое в версии 3.9.

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

Новое в версии 3.8.

Конкретные обобщённые коллекцииGeneric concrete collections

Соответствующие встроенным типамCorresponding to built-in types

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

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

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

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

Deprecated since version 3.9: builtins.dict now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

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

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

T = TypeVar('T', int, float)

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

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

Deprecated since version 3.9: builtins.list now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия builtins.set. Полезна для аннотирования возвращаемых типов. Для аннотирования аргументов предпочтительнее использовать абстрактный тип коллекции, например AbstractSet.

Deprecated since version 3.9: builtins.set now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия builtins.frozenset.

Deprecated since version 3.9: builtins.frozenset now supports subscripting ([]). See PEP 585 and Generic Alias Type.

Примечание

Tuple – это специальная форма.

Соответствует типам в collectionsCorresponding to types in collections

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

Обобщённая версия collections.defaultdict.

Новое в версии 3.5.2.

Deprecated since version 3.9: collections.defaultdict now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.OrderedDict.

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

Deprecated since version 3.9: collections.OrderedDict now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.ChainMap.

Новое в версии 3.5.4.

Новое в версии 3.6.1.

Deprecated since version 3.9: collections.ChainMap now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.Counter.

Новое в версии 3.5.4.

Новое в версии 3.6.1.

Deprecated since version 3.9: collections.Counter now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.deque.

Новое в версии 3.5.4.

Новое в версии 3.6.1.

Deprecated since version 3.9: collections.deque now supports subscripting ([]). See PEP 585 and Generic Alias Type.

Другие конкретные типыOther concrete types

class typing.IO
class typing.TextIO
class typing.BinaryIO

Обобщённый тип IO[AnyStr] и его подклассы TextIO(IO[str]) и BinaryIO(IO[bytes]) представляют типы потоков ввода-вывода, такие как возвращаемые open().

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

class typing.Pattern
class typing.Match

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

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

Устарело с версии 3.9: Классы Pattern и Match из re теперь поддерживают []. См. PEP 585 и Generic Alias Type.

class typing.Text

Text – это псевдоним для str. Он предоставляется для обеспечения совместимости с кодом Python 2: в Python 2 Text является псевдонимом для unicode.

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

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

Новое в версии 3.5.2.

Абстрактные базовые классыAbstract Base Classes

Соответствуют коллекциям из collections.abcCorresponding to collections in collections.abc

class typing.AbstractSet(Collection[T_co])

Обобщённая версия collections.abc.Set.

Deprecated since version 3.9: collections.abc.Set now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.ByteString(Sequence[int])

Обобщённая версия collections.abc.ByteString.

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

В качестве сокращения для этого типа bytes можно использовать для аннотации аргументов любого из упомянутых выше типов.

Deprecated since version 3.9: collections.abc.ByteString now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.abc.Collection

Новое в версии 3.6.0.

Deprecated since version 3.9: collections.abc.Collection now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.Container(Generic[T_co])

Обобщённая версия collections.abc.Container.

Deprecated since version 3.9: collections.abc.Container now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.abc.ItemsView.

Deprecated since version 3.9: collections.abc.ItemsView now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.abc.KeysView.

Deprecated since version 3.9: collections.abc.KeysView now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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]

Deprecated since version 3.9: collections.abc.Mapping now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.MappingView(Sized)

Обобщённая версия collections.abc.MappingView.

Deprecated since version 3.9: collections.abc.MappingView now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.abc.MutableMapping.

Deprecated since version 3.9: collections.abc.MutableMapping now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.MutableSequence(Sequence[T])

Обобщённая версия collections.abc.MutableSequence.

Deprecated since version 3.9: collections.abc.MutableSequence now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.MutableSet(AbstractSet[T])

Обобщённая версия collections.abc.MutableSet.

Deprecated since version 3.9: collections.abc.MutableSet now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.abc.Sequence.

Deprecated since version 3.9: collections.abc.Sequence now supports subscripting ([]). See PEP 585 and Generic Alias Type.

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

Обобщённая версия collections.abc.ValuesView.

Deprecated since version 3.9: collections.abc.ValuesView now supports subscripting ([]). See PEP 585 and Generic Alias Type.

Соответствует другим типам в collections.abcCorresponding to other types in collections.abc

class typing.Iterable(Generic[T_co])

Обобщённая версия collections.abc.Iterable.

Deprecated since version 3.9: collections.abc.Iterable now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.Iterator(Iterable[T_co])

Обобщённая версия collections.abc.Iterator.

Deprecated since version 3.9: collections.abc.Iterator now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])

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

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

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

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

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

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

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

Deprecated since version 3.9: collections.abc.Generator now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.Hashable

Псевдоним для collections.abc.Hashable.

class typing.Reversible(Iterable[T_co])

Обобщённая версия collections.abc.Reversible.

Deprecated since version 3.9: collections.abc.Reversible now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.Sized

Псевдоним для collections.abc.Sized.

Асинхронное программированиеAsynchronous programming

class typing.Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co])

Обобщённая версия collections.abc.Coroutine. Вариантность и порядок переменных типа соответствуют таковым у Generator, например:

from collections.abc import Coroutine
c: Coroutine[list[str], str, int]  # Некоторая корутина, определённая в другом месте.
x = c.send('hi')                   # Выведенный тип 'x' – list[str].
async def bar() -> None:
    y = await c                    # Выведенный тип 'y' – int.

Новое в версии 3.5.3.

Deprecated since version 3.9: collections.abc.Coroutine now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra])

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

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

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

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

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

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

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

Новое в версии 3.6.1.

Deprecated since version 3.9: collections.abc.AsyncGenerator now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.AsyncIterable(Generic[T_co])

Обобщённая версия collections.abc.AsyncIterable.

Новое в версии 3.5.2.

Deprecated since version 3.9: collections.abc.AsyncIterable now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.AsyncIterator(AsyncIterable[T_co])

Обобщённая версия collections.abc.AsyncIterator.

Новое в версии 3.5.2.

Deprecated since version 3.9: collections.abc.AsyncIterator now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.Awaitable(Generic[T_co])

Обобщённая версия collections.abc.Awaitable.

Новое в версии 3.5.2.

Deprecated since version 3.9: collections.abc.Awaitable now supports subscripting ([]). See PEP 585 and Generic Alias Type.

Типы контекстных менеджеровContext manager types

class typing.ContextManager(Generic[T_co])

Обобщённая версия contextlib.AbstractContextManager.

Новое в версии 3.5.4.

Новое в версии 3.6.0.

Deprecated since version 3.9: contextlib.AbstractContextManager now supports subscripting ([]). See PEP 585 and Generic Alias Type.

class typing.AsyncContextManager(Generic[T_co])

Обобщённая версия contextlib.AbstractAsyncContextManager.

Новое в версии 3.5.4.

Новое в версии 3.6.2.

Deprecated since version 3.9: contextlib.AbstractAsyncContextManager now supports subscripting ([]). See PEP 585 and Generic Alias Type.

ПротоколыProtocols

Эти протоколы декорированы runtime_checkable().

class typing.SupportsAbs

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

class typing.SupportsBytes

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

class typing.SupportsComplex

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

class typing.SupportsFloat

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

class typing.SupportsIndex

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

Новое в версии 3.8.

class typing.SupportsInt

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

class typing.SupportsRound

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

Функции и декораторыFunctions and decorators

typing.cast(typ, val)

Приводит значение к типу.

Это возвращает значение без изменений. Для проверщика типов это сигнализирует, что возвращаемое значение имеет указанный тип, но во время выполнения мы намеренно ничего не проверяем (мы хотим, чтобы это было как можно быстрее).

@typing.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>

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

@typing.final

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

class Base:
    @final
    def done(self) -> None:
        ...
class Sub(Base):
    def done(self) -> None:  # Ошибка, выдаваемая проверщиком типов
        ...

@final
class Leaf:
    ...
class Other(Leaf):  # Ошибка, выдаваемая проверщиком типов
    ...

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

Новое в версии 3.8.

@typing.no_type_check

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

Это работает как декоратор класса или функции декоратор. В случае класса он рекурсивно применяется ко всем методам, определённым в этом классе (но не к методам, определённым в его суперклассах или подклассах).

Это изменяет функцию(и) на месте.

@typing.no_type_check_decorator

Декоратор, придающий другому декоратору эффект no_type_check().

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

@typing.type_check_only

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

Сам этот декоратор недоступен во время выполнения. Он в основном предназначен для пометки классов, определённых в файлах заглушек типов (type stub), если реализация возвращает экземпляр закрытого класса:

@type_check_only
class Response:  # приватный или недоступный во время выполнения
    code: int
    def get_header(self, name: str) -> str: ...

def fetch_response() -> Response: ...

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

Вспомогательные функции для интроспекцииIntrospection helpers

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

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

Это часто совпадает с obj.__annotations__. Кроме того, прямые ссылки, закодированные как строковые литералы, обрабатываются путём вычисления их в пространствах имён globals и locals. При необходимости Optional[t] добавляется для аннотаций функций и методов, если задано значение по умолчанию, равное None. Для класса C возвращается словарь, построенный объединением всех __annotations__ по C.__mro__ в обратном порядке.

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

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

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

Примечание

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

Изменено в версии 3.9: Добавлен параметр include_extras в рамках PEP 593.

typing.get_args(tp)
typing.get_origin(tp)

Предоставляют базовую интроспекцию для обобщённых типов и специальных форм typing.

Для объекта typing вида X[Y, Z, ...] эти функции возвращают X и (Y, Z, ...). Если X является обобщённым псевдонимом для встроенного класса или класса collections, он нормализуется до исходного класса. Если X является объединением или Literal, содержащимся в другом обобщённом типе, порядок (Y, Z, ...) может отличаться от порядка исходных аргументов [Y, Z, ...] из-за кэширования типов. Для неподдерживаемых объектов возвращают None и () соответственно. Примеры:

assert get_origin(Dict[str, int]) is dict
assert get_args(Dict[int, str]) == (int, str)

assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)

Новое в версии 3.8.

typing.is_typeddict(tp)

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

Например:

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

is_typeddict(Film)  # => True
is_typeddict(list | str)  # => False

Новое в версии 3.10.

class typing.ForwardRef

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

Примечание

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

Новое в версии 3.7.4.

КонстантаConstant

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

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

Примечание

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

Новое в версии 3.5.2.