Spec-Zone.ru › Python 3.11

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

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

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

Примечание

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

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

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

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

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

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

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

См. также

“Справочник по типу”

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

Раздел “Справочник по системе типов” документации mypy

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

“Статическая типизация с Python”

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

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

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

Полный список PEP
  • 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 646: Многоаргументные дженерики

    Введение TypeVarTuple

  • PEP 647: Защищенные от ошибок типы

    Введение TypeGuard

  • PEP 655: Отмечание отдельных элементов TypedDict как обязательных или потенциально отсутствующих

    Введение Required и NotRequired

  • PEP 673: Тип self

    Введение Self

  • PEP 675: Произвольный строковый тип литерала

    Введение LiteralString

  • PEP 681: Преобразования классов данных

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


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

Псевдоним типа определяется путем присвоения типа псевдониму. В этом примере 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:
    ...

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

from typing import TypeAlias

Vector: TypeAlias = list[float]
END_OF_DOCUMENT_MARKER

Новый тип

Используйте помощник 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: Производительность вызова NewType восстановлена до уровня Python 3.9.

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

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

Например:

from collections.abc import Callable, Awaitable

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

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

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

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

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

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

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

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

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

from collections.abc import Iterable
from typing import Protocol

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

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

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

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

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

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

См. также

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

Обобщения

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

from collections.abc import Mapping, Sequence

class Employee: ...

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

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

from collections.abc import Sequence
from typing import TypeVar

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

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

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

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

from collections.abc import Mapping

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

type[Any] эквивалентно type, которое является корнем иерархии метаклассов Python.

END_OF_DOCUMENT_MARKER

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

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

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

END_OF_DOCUMENT_MARKER

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

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

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

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

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

typing.Any

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

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

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

typing.AnyStr

Переменная ограниченная переменная типа.

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

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

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

Например:

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

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

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

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

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

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

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

Пример:

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

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

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

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

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

typing.Never

Тип «нижнего уровня» (bottom type), тип, у которого нет элементов.

Его можно использовать для определения функции, которая никогда не должна вызываться, или функции, которая никогда не возвращает значение:

from typing import Never

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

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

Добавлен в версии 3.11: В более старых версиях Python для выражения той же концепции может использоваться NoReturn. Never был добавлен для более явного выражения намерений.

typing.NoReturn

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

Например:

from typing import NoReturn

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

NoReturn также может использоваться как тип «нижнего уровня» (bottom type), тип, у которого нет значений. Начиная с Python 3.11, для этой концепции следует использовать тип Never. Инструменты проверки типов должны рассматривать эти два типа эквивалентными.

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

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

typing.Self

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

Например:

from typing import Self, reveal_type

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

class SubclassOfFoo(Foo): pass

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

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

from typing import TypeVar

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

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

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

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

  • classmethod, которые используются как альтернативные конструкторы и возвращают экземпляры параметра cls.
  • Аннотация метода __enter__(), который возвращает self.

Вы не должны использовать Self в качестве аннотации возвращаемого значения, если метод не гарантированно возвращает экземпляр подкласса при наследовании от класса:

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

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

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

typing.TypeAlias

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

Например:

from typing import TypeAlias

Factors: TypeAlias = list[int]

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

from typing import Generic, TypeAlias, TypeVar

T = TypeVar("T")

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

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

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

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

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

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

typing.Union

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

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

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

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

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

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

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

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

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

typing.Optional

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

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

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

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

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

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

typing.Concatenate

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

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

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

from collections.abc import Callable
from threading import Lock
from typing import Concatenate, 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
  • Аннотирование вызываемых объектов
typing.Literal

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

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

Например:

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

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

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

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

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

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

typing.ClassVar

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

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

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

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

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

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

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

typing.Final

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

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

Например:

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

class Connection:
    TIMEOUT: Final[int] = 10

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

Нет проверки этих свойств во время выполнения. См. PEP 591 для получения дополнительной информации.

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

typing.Required

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

Это в основном полезно для total=False TypedDicts. См. TypedDict и PEP 655 для получения дополнительной информации.

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

typing.NotRequired

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

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

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

typing.Annotated

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

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

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

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

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

Annotated[<type>, <metadata>]

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

@dataclass
class ValueRange:
    lo: int
    hi: int

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

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

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

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

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

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

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

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

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

    @dataclass
    class MaxLen:
        value: int
    
    T = TypeVar("T")
    Vec: TypeAlias = Annotated[list[tuple[T, T]], MaxLen(10)]
    
    assert Vec[int] == Annotated[list[tuple[int, int]], MaxLen(10)]
    
  • Annotated нельзя использовать с распакованным TypeVarTuple:

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

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

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

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

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

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

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

См. также

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

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

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

typing.TypeGuard

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

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

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

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

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

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

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

Например:

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

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

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

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

Примечание

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

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

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

typing.Unpack

Оператор типизации, концептуально отмечающий объект как распакованный.

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

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

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

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

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

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

Создание универсальных типов

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

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(name, *constraints, bound=None, covariant=False, contravariant=False)

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

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

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

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

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

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

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

class StringSubclass(str):
    pass

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

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

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

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

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

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

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

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

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

__name__

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

__covariant__

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

__contravariant__

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

__bound__

Связь переменной типа, если она есть.

__constraints__

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

class typing.TypeVarTuple(name)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

DType = TypeVar('DType')
Shape = TypeVarTuple('Shape')

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

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

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

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

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

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

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

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

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

См. PEP 646 для получения дополнительной информации о кортежах переменных типа.

__name__

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

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

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

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

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

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.

__name__

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

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

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

Примечание

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

См. также

  • PEP 612 – Переменные спецификации параметров (PEP, который представил ParamSpec и Concatenate)
  • Concatenate
  • Аннотирование вызываемых объектов
typing.ParamSpecArgs
END_OF_DOCUMENT_MARKER
typing.ParamSpecKwargs

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

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

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

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

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

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

class typing.NamedTuple

Типизированный аналог collections.namedtuple().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Обратная совместимость:

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

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

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

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

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

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

class typing.NewType(name, tp)

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

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

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

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

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

__name__

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

__supertype__

Тип, на основе которого создан новый тип.

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

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

class typing.Protocol(Generic)

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

Классы-протоколы определяются так:

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

В основном такие классы используются с проверками статических типов, которые распознают структурное подтипирование (статическое «пёстрое наследование»), например:

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

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

func(C())  # Passes static type check

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

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

T = TypeVar("T")

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

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

@typing.runtime_checkable

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

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

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

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

@runtime_checkable
class Named(Protocol):
    name: str

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

Примечание

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

Примечание

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

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

class typing.TypedDict(dict)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class Point3D(Point2D):
    z: int

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

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

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

class X(TypedDict):
    x: int

class Y(TypedDict):
    y: int

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

class XY(X, Y): pass  # OK

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

TypedDict может быть обобщённым:

T = TypeVar("T")

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

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

__total__

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

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

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

__required_keys__

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

__optional_keys__

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

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

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

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

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

Примечание

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

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

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

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

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

Протоколы

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

class typing.SupportsAbs

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

class typing.SupportsBytes

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

class typing.SupportsComplex

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

class typing.SupportsFloat

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

class typing.SupportsIndex

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

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

class typing.SupportsInt

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

class typing.SupportsRound

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

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

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

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

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

typing.cast(typ, val)

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

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

typing.assert_type(val, typ, /)

Запрос к статическому анализатору типов для подтверждения, что val имеет предполагаемый тип typ.

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

Когда статический анализатор типов сталкивается с вызовом assert_type(), он выдает ошибку, если значение не соответствует указанному типу:

def greet(name: str) -> None:
    assert_type(name, str)  # OK, inferred type of `name` is `str`
    assert_type(name, int)  # type checker error

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

def complex_function(arg: object):
    # Do some complex type-narrowing logic,
    # after which we hope the inferred type will be `int`
    ...
    # Test whether the type checker correctly understands our function
    assert_type(arg, int)

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

typing.assert_never(arg, /)

Запрос к статическому анализатору типов для подтверждения того, что строка кода недостижима.

Пример:

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

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

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

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

См. также

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

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

typing.reveal_type(obj, /)

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

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

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

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

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

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

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

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

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

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

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

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

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

T = TypeVar("T")

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

@create_model
class CustomerModel:
    id: int
    name: str

Для базового класса:

@dataclass_transform()
class ModelBase: ...

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

Для метакласса:

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

class ModelBase(metaclass=ModelMeta): ...

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

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

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

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

Параметры
  • eq_default (bool) – Указывает, предполагается ли параметр eq равным True или False если он опущен вызывающей стороной. По умолчанию True.
  • order_default (bool) – Указывает, предполагается ли параметр order равным True или False если он опущен вызывающей стороной. По умолчанию False.
  • kw_only_default (bool) – Указывает, предполагается ли параметр kw_only равным True или False если он опущен вызывающей стороной. По умолчанию False.
  • field_specifiers (tuple[Callable[..., Any], ...]) – Указывает статический список поддерживаемых классов или функций, описывающих поля, аналогично dataclasses.field(). По умолчанию ().
  • **kwargs (Any) – Принимаются произвольные дополнительные ключевые аргументы, чтобы позволить возможные будущие расширения.

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

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

Название параметра

Описание

init

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

default

Предоставляет значение по умолчанию для поля.

default_factory

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

factory

Псевдоним для параметра default_factory в спецификаторах полей.

kw_only

Указывает, должно ли поле отмечаться как только для ключевых аргументов. Если True, поле будет только ключевым. Если False, оно не будет только ключевым. Если не указано, используется значение параметра kw_only на объекте, декорированном dataclass_transform, или если это не указано, используется значение kw_only_default на dataclass_transform.

alias

Предоставляет альтернативное имя для поля. Это альтернативное имя используется в синтезированном методе __init__.

Во время выполнения этот декоратор записывает свои аргументы в атрибут __dataclass_transform__ на декорируемом объекте. Он не имеет других эффектов во время выполнения.

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

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

@typing.overload

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

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

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

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

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

См. PEP 484 для получения более подробной информации и сравнения с другими семантиками типов.

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

typing.get_overloads(func)

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

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

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

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

typing.clear_overloads()

Очищает все зарегистрированные перегрузки в внутренней базе данных.

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

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

@typing.final

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

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

Например:

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

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

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

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

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

@typing.no_type_check

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

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

@no_type_check изменяет объект, к которому применяется декоратор, непосредственно.

@typing.no_type_check_decorator

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

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

@typing.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. Для класса C, возвращается словарь, составленный путём объединения всех __annotations__ в порядке C.__mro__ в обратном порядке.

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

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

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

Примечание

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

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

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

typing.get_origin(tp)

Получить версию типа без подстановочных значений: для объекта typing вида X[Y, Z, ...] возвращает X.

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

Примеры:

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

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

typing.get_args(tp)

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

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

Примеры:

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

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

typing.is_typeddict(tp)

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

Например:

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

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

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

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

class typing.ForwardRef

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

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

Примечание

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

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

Константа

typing.TYPE_CHECKING

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

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

if TYPE_CHECKING:
    import expensive_mod

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

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

Примечание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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, а не set или typing.Set.

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

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

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

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

typing.Tuple

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

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

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

class typing.Type(Generic[CT_co])

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

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

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

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

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

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

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

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

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

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

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

Новая версия 3.7.2.

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

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

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

Новая версия 3.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.Pattern
class typing.Match

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

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

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

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

class typing.Text

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

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

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

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

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

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

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

class typing.AbstractSet(Collection[T_co])

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

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

class typing.ByteString(Sequence[int])

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

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

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 и Тип обобщенного псевдонима.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.AsyncIterable(Generic[T_co])

Устаревшее псевдоним к collections.abc.AsyncIterable.

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

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

class typing.AsyncIterator(AsyncIterable[T_co])

Устаревшее псевдоним к collections.abc.AsyncIterator.

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

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

class typing.Awaitable(Generic[T_co])

Устаревшее псевдоним к collections.abc.Awaitable.

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

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

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

class typing.Iterable(Generic[T_co])

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

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

class typing.Iterator(Iterable[T_co])

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

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

typing.Callable

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.Hashable

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

class typing.Reversible(Iterable[T_co])

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

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

class typing.Sized

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

Псевдонимы для contextlib ABC

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 и Тип Обобщенного Псевдонима.

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

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

Функция

Устарела в

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

PEP/вопрос

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

3.8

3.13

bpo-38291

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

3.9

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

PEP 585

typing.ByteString

3.9

3.14

gh-91896

typing.Text

3.11

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

gh-92332

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

Spec-Zone.ru

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