Spec-Zone.ru › Python 3.10

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.

См. также

Для быстрого обзора подсказок типов обратитесь к этой шпаргалке.

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

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

Соответствующие PEP

С момента первоначального введения подсказок типов в 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: Allow writing union types as X | Y

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

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

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

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

from collections.abc import Sequence

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

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

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

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

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

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

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

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

from typing import NewType

UserId = NewType('UserId', int)

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

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

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

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

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

Примечание

Помните, что использование псевдонима типа объявляет два типа как эквивалентные друг другу. Выполнение 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: ...

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

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

Тип Any

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

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

from typing import Any

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

s: str = ''
s = a           # OK

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

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

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

def legacy_parser(text):
    ...
    return data

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

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

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

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

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

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

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

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

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

Номинальный против структурного суператипирования

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

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

from collections.abc import Sized, Iterable, Iterator

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

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

from collections.abc import Iterator, Iterable

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

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

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

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

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

Примечание

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

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

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

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

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

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

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.

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

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

typing.Tuple

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

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

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

typing.Optional

Тип необязательный.

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

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

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

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

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

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

typing.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 ожидает вызываемый объект, принимающий Lock в качестве первого аргумента и возвращающий вызываемый объект с другой сигнатурой типа. В этом случае 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, переменные типов и объединения любых из этих типов. Например:

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

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 с помощью аннотации типа 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" type guard
    if isinstance(val, str):
        # Type of ``val`` is narrowed to ``str``
        ...
    else:
        # Else, type of ``val`` is narrowed to ``float``.
        ...

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

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

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

Например:

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

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

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

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

Примечание

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

TypeGuard также работает с переменными типов. Подробнее см. PEP 647.

Введено в версии 3.10.

Создание обобщённых типов

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

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

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

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

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

Изменено в версии 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})

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

# 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. Можно переопределить это, указав полноту. Использование:

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

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

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

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

Введено в версии 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().

Устарело начиная с версии 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 и Тип обобщённого псевдонима.

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.

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

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

class typing.AbstractSet(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, AbstractSet[tuple[KT_co, VT_co]])

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

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

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

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

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

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

Обобщенная версия collections.abc.Mapping. Этот тип можно использовать следующим образом:

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

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

class typing.MappingView(Sized)

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

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

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

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

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

class typing.MutableSequence(Sequence[T])

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

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

class typing.MutableSet(AbstractSet[T])

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

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

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

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

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

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

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

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

Соответствующие другим типам в 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'

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

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

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

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

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

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

class typing.Hashable

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

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, напрямую будет поднята ошибка 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

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

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

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

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

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

Spec-Zone.ru

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