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

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

Соответствующие ПЭП

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

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

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

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

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

  • PEP 585: Generics с подсказкой типа в стандартных коллекциях

    Введение types.GenericAlias и возможность использования классов стандартной библиотеки в качестве generic types.

  • PEP 586: Буквальные типы

    Введение Literal

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

    Введение TypedDict

  • PEP 591: Добавление последнего квалификатора к набору текста

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

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

    Введение Annotated

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

    Введение types.UnionType и возможность использования оператора бинарного или | для обозначения union of types

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

    Введение ParamSpec и Concatenate

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

    Введение TypeAlias

  • PEP 647: Охрана типов, определяемая пользователем

    Введение TypeGuard

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

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

Vector = list[float]

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

# typechecks; a list of floats qualifies as a 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:
    ...

# 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:
    ...

Обратите внимание, что 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:
    ...

# typechecks
user_a = get_user_name(UserId(42351))

# does not typecheck; 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 typecheck
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[[Arg1Type, Arg2Type], ReturnType].

Например:

from collections.abc import Callable

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

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

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

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

Генерики могут быть параметризованы с помощью фабрики, доступной в типизации под названием TypeVar.

from collections.abc import Sequence
from typing import TypeVar

T = TypeVar('T')      # Declare type variable

def first(l: Sequence[T]) -> T:   # Generic function
    return l[0]

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

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

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): # Same as Iterable[Any]

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

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

# Return type here is same as 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: # Same as Iterable[tuple[T, T]]
    return sum(x*y for x, y in v)

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

Определяемые пользователем дженерики для выражений параметров также поддерживаются через переменные спецификации параметров в форме Generic[P]. Поведение соответствует описанному выше поведению переменных типов, поскольку переменные спецификации параметров рассматриваются модулем типизации как специализированные переменные типов. Единственным исключением является то, что список типов может быть использован для замены 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'>)]

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

Тип 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:
    # Typechecks; '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; an object does not have a 'magic' method.
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Typechecks
    item.magic()
    ...

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

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

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

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

Примечание

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

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

Устаревшие типы будут удалены из модуля typing в первой версии Python, выпущенной через 5 лет после выхода Python 3.9.0. Подробности см. в PEP 585-Типовая подсказка Generics In Standard Collections.

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

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

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

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

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

from typing import TypeAlias

Factors: TypeAlias = list[int]

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

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

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

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

typing.Tuple

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

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

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

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

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: Optional теперь можно записать как X | None. См. union type expressions.

typing.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] соответственно.

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

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

См.также

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

typing.Concatenate

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

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

from collections.abc import Callable
from threading import Lock
from typing import Concatenate, ParamSpec, TypeVar

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

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

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

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

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

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

См.также

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

  • ParamSpec и Callable.

class typing.Type(Generic[CT_co])

Переменная, аннотированная C, может принимать значение типа C. Напротив, переменная, аннотированная 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 BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...

# Accepts User, BasicUser, ProUser, TeamUser, ...
def make_new_user(user_class: Type[User]) -> User:
    # ...
    return user_class()

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

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

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

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

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

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

typing.Literal

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

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

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

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

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

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

Изменено в версии 3.9.1: Literal теперь не дублирует параметры. Сравнение равенства объектов Literal больше не зависит от порядка. Объекты Literal теперь будут вызывать исключение TypeError при сравнении равенства, если один из их параметров не является 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

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

typing.Final

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

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

class Connection:
    TIMEOUT: Final[int] = 10

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

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

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

typing.Annotated

Тип, введенный в PEP 593 (Flexible function and variable annotations), для украшения существующих типов контекстно-зависимыми метаданными (возможно, несколькими частями, поскольку Annotated является переменным). В частности, тип T может быть аннотирован метаданными x через typehint Annotated[T, x]. Эти метаданные могут быть использованы как для статического анализа, так и во время выполнения. Если библиотека (или инструмент) встречает typehint 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" type guard
    if isinstance(val, str):
        # Type of ``val`` is narrowed to ``str``
        ...
    else:
        # Else, type of ``val`` is narrowed to ``float``.
        ...

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

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

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

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

Например:

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

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

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

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

Примечание

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

TypeGuard также работает с переменными типа. Для получения дополнительной информации смотрите PEP 647 (Охрана типов, определяемых пользователем).

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

Построение общих типов

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

class typing.Generic

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

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

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

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

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')  # 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(x: T, n: int) -> Sequence[T]:
    """Return a list containing n references to x."""
    return [x]*n


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


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

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

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

a = concatenate('one', 'two')  # Ok, variable 'a' has type 'str'
b = concatenate(StringSubclass('one'), StringSubclass('two'))  # Inferred type of variable 'b' 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

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

print_capitalized('a string')  # Ok, output has type 'str'

class StringSubclass(str):
    pass

print_capitalized(StringSubclass('another string'))  # Ok, output has type 'StringSubclass'
print_capitalized(45)  # error: int is not a subtype of str

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

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

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

import math

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

class Circle:
    """An abstract circle"""

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

    # Use a type variable to show that the return type
    # will always be an instance of whatever ``cls`` is
    @classmethod
    def with_circumference(cls: type[C], circumference: float) -> C:
        """Create a circle with the specified circumference"""
        radius = circumference / (math.pi * 2)
        return cls(radius)


class Tire(Circle):
    """A specialised circle (made out of rubber)"""

    MATERIAL = 'rubber'


c = Circle.with_circumference(3)  # Ok, variable 'c' has type 'Circle'
t = Tire.with_circumference(4)  # Ok, variable 't' has type 'Tire' (not '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]:
    '''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 соответственно.

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

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

Примечание

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

См.также

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

  • Callable и Concatenate.

typing.ParamSpecArgs
typing.ParamSpecKwargs

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

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

P = ParamSpec("P")
get_origin(P.args)  # returns P
get_origin(P.kwargs)  # returns 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")  # Ok, output has type 'unicode'
concat(b"foo", b"bar")  # Ok, output has type 'bytes'
concat(u"foo", b"bar")  # Error, cannot mix unicode and 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())  # Passes static type check

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

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

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

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

@typing.runtime_checkable

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

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

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

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

Примечание

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

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

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

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

class typing.NamedTuple

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Employee = NamedTuple('Employee', [('name', str), ('id', int)])

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

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

Изменено в версии 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'}  # OK
b: Point2D = {'z': 3, 'label': 'bad'}           # Fails type check

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

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

Point2D = TypedDict('Point2D', x=int, y=int, label=str)
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. Это можно отменить, указав значение total. Использование:

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  # A non-TypedDict class

class XY(X, Y): pass  # OK

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

T = TypeVar('T')
class XT(X, Generic[T]): pass  # raises TypeError

Аннотация 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
__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.

Общие конкретные коллекции

Соответствие встроенным типам

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

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

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

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

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

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]

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

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

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

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

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

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

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

Примечание

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

Соответствие типам в collections

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Другие виды бетона

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

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

Deprecated since version 3.8, will be removed in version 3.12: Пространство имен typing.io устарело и будет удалено. Вместо этого эти типы следует напрямую импортировать из typing.

class typing.Pattern
class typing.Match

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

Deprecated since version 3.8, will be removed in version 3.12: Пространство имен typing.re устарело и будет удалено. Вместо этого эти типы следует напрямую импортировать из typing.

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

class typing.Text

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

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

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

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

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

Соответствие коллекциям в collections.abc.

class typing.AbstractSet(Sized, Collection[T_co])

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

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

class typing.ByteString(Sequence[int])

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

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

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

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

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

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

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

Не рекомендуется, начиная с версии 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, Generic[KT_co, VT_co])

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

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

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

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

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

class typing.Mapping(Sized, Collection[KT], Generic[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, Iterable[T_co])

Обобщенная версия 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[VT_co])

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

Не рекомендуется, начиная с версии 3.9: collections.abc.ValuesView теперь поддерживает []. См. 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 и Общий тип псевдонима.

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'

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

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

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

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

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

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

class typing.Hashable

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

class typing.Reversible(Iterable[T_co])

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

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

class typing.Sized

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

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

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]  # Some coroutine defined elsewhere
x = c.send('hi')                   # Inferred type of 'x' is list[str]
async def bar() -> None:
    y = await c                    # Inferred type of 'y' is int

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

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

class typing.AsyncGenerator(AsyncIterator[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.

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

class typing.AsyncIterable(Generic[T_co])

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

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

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

class typing.AsyncIterator(AsyncIterable[T_co])

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

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

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

class typing.Awaitable(Generic[T_co])

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

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

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

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

class typing.ContextManager(Generic[T_co])

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

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

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

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

class typing.AsyncContextManager(Generic[T_co])

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

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

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

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

Протоколы

Эти протоколы украшаются символом 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__, который является ковариантным в своем возвращаемом типе.

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

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:  # Error reported by type checker
        ...

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

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

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

@typing.no_type_check

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

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

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

@typing.no_type_check_decorator

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

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

@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. Если необходимо, 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() не работает с импортированными type aliases, которые включают прямые ссылки. Включение отложенной оценки аннотаций (PEP 563) может устранить необходимость в большинстве прямых ссылок.

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

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

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

Для типизированного объекта вида 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.

Постоянная

typing.TYPE_CHECKING

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

if TYPE_CHECKING:
    import expensive_mod

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

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

Примечание

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

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

Вернуться на верх