Spec-Zone.ru › Python 3.13

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

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

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

Примечание

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

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

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

def surface_area_of_cube(edge_length: float) -> str:
    return f"The surface area of the cube is {6 * edge_length ** 2}."

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

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

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

См. также

Шпаргалка по типизации

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

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

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

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

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

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

Актуальную каноническую спецификацию системы типов Python можно найти в документе Спецификация системы типов Python.

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

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

type Vector = list[float]

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

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

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

from collections.abc import Sequence

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

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

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

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

Vector = list[float]

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

from typing import TypeAlias

Vector: TypeAlias = list[float]

NewType

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

from typing import NewType

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

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

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

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

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

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

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

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

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

Создавать подкласс Derived недопустимо:

from typing import NewType

UserId = NewType('UserId', int)

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

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

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

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

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

Примечание

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

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

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

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

from collections.abc import Sequence

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

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

from collections.abc import Sequence
from typing import TypeVar

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

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

Изменено в версии 3.12: Синтаксическая поддержка обобщённых типов появилась в Python 3.12.

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

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

from collections.abc import Mapping

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

Эти типы также можно указать явно:

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

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

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

Асинхронные генераторы обрабатываются аналогичным образом, но у них не указывается аргумент типа ReturnType (AsyncGenerator[YieldType, SendType]). Аргумент SendType по умолчанию равен None, поэтому следующие определения эквивалентны:

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

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

Как и в синхронном случае, доступны также AsyncIterable[YieldType] и AsyncIterator[YieldType]:

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

Сопрограммы можно аннотировать с помощью Coroutine[YieldType, SendType, ReturnType]. Обобщённые аргументы соответствуют аргументам 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

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

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

from logging import Logger

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

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

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

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

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

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

from typing import TypeVar, Generic

T = TypeVar('T')

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

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

from collections.abc import Iterable

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

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

from typing import TypeVar, Generic, Sequence

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

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

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

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

from typing import TypeVar, Generic
...

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

T = TypeVar('T')

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

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

from collections.abc import Sized

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

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

from collections.abc import Mapping

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

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

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

from collections.abc import Iterable

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

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

from collections.abc import Iterable

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

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

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

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

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

from collections.abc import Iterable
from typing import TypeVar

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

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

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

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

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

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

from typing import ParamSpec, Generic

P = ParamSpec('P')

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

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

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

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

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

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

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

Модуль 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!"

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

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

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

Never и NoReturn представляют нижний тип — тип, у которого нет элементов.

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

from typing import Never  # or NoReturn

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

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

from typing import Never  # or NoReturn

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

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

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

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

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

typing.Self

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

Например:

from typing import Self, reveal_type

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

class SubclassOfFoo(Foo): pass

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

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

from typing import TypeVar

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

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

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

Другие распространённые случаи применения:

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

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

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 особенно полезен в старых версиях Python для аннотирования псевдонимов, использующих предварительные ссылки, поскольку средствам проверки типов может быть сложно отличить их от обычных присваиваний переменным:

from typing import Generic, TypeAlias, TypeVar

T = TypeVar("T")

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

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

Подробнее см. в PEP 613.

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

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

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

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

typing.Union

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

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

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

    Union[Union[int, str], float] == Union[int, str, float]
    

    Однако это не относится к объединениям, на которые ссылаются через псевдоним типа, чтобы не требовать вычисления базового TypeAliasType:

    type A = Union[int, str]
    Union[A, 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

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

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

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

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

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

См. также

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

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

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

Например:

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

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

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

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

Дополнительные сведения:

  • Аргументы должны быть литеральными значениями, и должен быть указан хотя бы один аргумент.
  • Вложенные типы Literal уплощаются, например:

    assert Literal[Literal[1, 2], 3] == Literal[1, 2, 3]
    

    Однако это не относится к типам Literal, на которые ссылаются через псевдоним типа, чтобы не требовать вычисления базового TypeAliasType:

    type A = Literal[1, 2]
    assert Literal[A, 3] != Literal[1, 2, 3]
    
  • Повторяющиеся аргументы пропускаются, например:

    assert Literal[1, 2, 1] == Literal[1, 2]
    
  • При сравнении литералов порядок аргументов не учитывается, например:

    assert Literal[1, 2] == Literal[2, 1]
    
  • Нельзя создавать подклассы Literal или экземпляры этого типа.
  • Нельзя записывать Literal[X][Y].

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

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

typing.Final

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

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

Например:

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

class Connection:
    TIMEOUT: Final[int] = 10

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

Эти свойства не проверяются во время выполнения. Дополнительные сведения см. в PEP 591.

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

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

typing.Required

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

Это особенно полезно для total=False TypedDict. Дополнительные сведения см. в TypedDict и PEP 655.

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

typing.NotRequired

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

Дополнительные сведения см. в TypedDict и PEP 655.

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

typing.ReadOnly

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

Например:

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

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

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

Дополнительные сведения см. в TypedDict и PEP 705.

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

typing.Annotated

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

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

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

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

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

Annotated[<type>, <metadata>]

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

@dataclass
class ValueRange:
    lo: int
    hi: int

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

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

@dataclass
class ctype:
     kind: str

a1 = Annotated[int, ValueRange(3, 10), ctype("char")]
a2 = Annotated[int, ctype("char"), ValueRange(3, 10)]

assert a1 != a2  # Order matters

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

Вложенные типы Annotated уплощаются. Порядок элементов метаданных начинается с самой внутренней аннотации:

assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
    int, ValueRange(3, 10), ctype("char")
]

Однако это не относится к типам Annotated, на которые ссылаются через псевдоним типа, чтобы не требовать вычисления базового TypeAliasType:

type From3To10[T] = Annotated[T, ValueRange(3, 10)]
assert Annotated[From3To10[int], ctype("char")] != Annotated[
   int, ValueRange(3, 10), ctype("char")
]

Повторяющиеся элементы метаданных не удаляются:

assert Annotated[int, ValueRange(3, 10)] != Annotated[
    int, ValueRange(3, 10), ValueRange(3, 10)
]

Annotated можно использовать с вложенными и обобщёнными псевдонимами:

@dataclass
class MaxLen:
    value: int

type Vec[T] = Annotated[list[tuple[T, T]], MaxLen(10)]

# When used in a type annotation, a type checker will treat "V" the same as
# ``Annotated[list[tuple[int, int]], MaxLen(10)]``:
type V = Vec[int]

Annotated нельзя использовать с распакованным TypeVarTuple:

type Variadic[*Ts] = Annotated[*Ts, Ann1] = Annotated[T1, T2, T3, ..., Ann1]  # NOT valid

где 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')

Чтобы получить исходный тип, обёрнутый в Annotated, используйте атрибут __origin__:

>>> from typing import Annotated, get_origin
>>> Password = Annotated[str, "secret"]
>>> Password.__origin__
<class 'str'>

Обратите внимание, что вызов get_origin() вернёт сам Annotated:

>>> get_origin(Password)
typing.Annotated

См. также

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

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

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

typing.TypeIs

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

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

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

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

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

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

  1. Возвращаемое значение является логическим.
  2. Если возвращаемое значение — True, тип аргумента представляет собой пересечение исходного типа аргумента и NarrowedType.
  3. Если возвращаемое значение — False, тип аргумента сужается с исключением NarrowedType.

Например:

from typing import assert_type, final, TypeIs

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

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

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

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

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

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

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

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

typing.TypeGuard

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

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

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

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

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

Например:

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

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

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

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

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

typing.Unpack

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

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

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

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

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

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

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

from typing import TypedDict, Unpack

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

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

Дополнительные сведения об использовании Unpack для типизации **kwargs см. в PEP 692.

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

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

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

Эти объекты можно создавать с помощью специального синтаксиса (списки параметров типа и инструкции type). Для совместимости с Python 3.11 и более ранними версиями их также можно создавать без специального синтаксиса, как описано ниже.

class typing.Generic

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class StrSequence[S: str]:  # S is a TypeVar with a `str` upper bound;
    ...                     # we can say that S is "bounded by `str`"


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

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

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

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

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


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


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

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

Ковариантность или контравариантность переменных типа выводится анализаторами типов, если переменные создаются с помощью синтаксиса параметров типа или передаётся infer_variance=True. Переменные типа, созданные вручную, можно явно пометить как ковариантные или контравариантные, передав covariant=True или contravariant=True. По умолчанию переменные типа, созданные вручную, инвариантны. Подробнее см. в PEP 484 и PEP 695.

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

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

class StringSubclass(str):
    pass

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

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

Верхней границей переменной типа может быть конкретный тип, абстрактный тип (ABC или Protocol) или даже объединение типов:

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

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

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

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

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

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

Во время выполнения isinstance(x, T) вызовет исключение TypeError.

__name__

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

__covariant__

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

__contravariant__

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

__infer_variance__

Указывает, должны ли анализаторы типов выводить вариантность переменной типа.

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

__bound__

Верхняя граница переменной типа, если она задана.

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

__constraints__

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

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

__default__

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

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

has_default()

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

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

Изменено в версии 3.12: Теперь переменные типа можно объявлять с помощью синтаксиса параметров типа, представленного в PEP 695. Добавлен параметр infer_variance.

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

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

Кортеж переменных типа. Специализированная форма переменной типа, поддерживающая вариативные обобщения.

Кортежи переменных типа можно объявлять в списках параметров типа, ставя одну звёздочку (*) перед именем:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

__name__

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

__default__

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

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

has_default()

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

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

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

Изменено в версии 3.12: Теперь кортежи переменных типа можно объявлять с помощью синтаксиса параметров типа, представленного в PEP 695.

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

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

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

В списках параметров типа спецификации параметров можно объявлять, ставя две звёздочки (**):

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

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

P = ParamSpec('P')

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

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

from collections.abc import Callable
import logging

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

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

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

  1. Анализатор типов не может проверить типы функции inner, поскольку *args и **kwargs должны иметь тип Any.
  2. В теле декоратора add_logging может потребоваться cast() при возврате функции inner либо анализатору статических типов потребуется указать игнорировать return inner.
args
kwargs

Поскольку ParamSpec охватывает позиционные и именованные параметры, P.args и P.kwargs можно использовать, чтобы разделить ParamSpec на составляющие. P.args представляет собой кортеж позиционных параметров в данном вызове и должен использоваться только для аннотации *args. P.kwargs представляет собой соответствие между именованными параметрами и их значениями в данном вызове и должен использоваться только для аннотации **kwargs. Оба атрибута требуют, чтобы аннотируемый параметр находился в области видимости. Во время выполнения P.args и P.kwargs являются экземплярами соответственно ParamSpecArgs и ParamSpecKwargs.

__name__

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

__default__

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

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

has_default()

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

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

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

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

Изменено в версии 3.12: Теперь спецификации параметров можно объявлять с помощью синтаксиса параметров типа, представленного в PEP 695.

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

Примечание

Сериализовать с помощью pickle можно только переменные спецификации параметров, определённые в глобальной области видимости.

См. также

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

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

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

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

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

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

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

Пример:

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

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

__name__

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

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

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

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

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

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

Значение псевдонима типа. Оно вычисляется отложенно, поэтому имена, используемые в определении псевдонима, разрешаются только при обращении к атрибуту __value__:

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

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

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

class typing.NamedTuple

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

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

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

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

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

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

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

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

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

У полученного класса есть дополнительный атрибут __annotations__, содержащий словарь, который сопоставляет имена полей с типами полей. (Имена полей находятся в атрибуте _fields, а значения по умолчанию — в атрибуте _field_defaults; оба входят в 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[T](NamedTuple):
    key: T
    group: list[T]

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

# For creating a generic NamedTuple on Python 3.11
T = TypeVar("T")

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

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

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

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

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

Изменено в версии 3.9: Атрибут _field_types удалён в пользу более стандартного атрибута __annotations__, содержащего те же сведения.

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

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

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

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() (описанного далее), выступают в роли простых протоколов времени выполнения: они проверяют только наличие заданных атрибутов, игнорируя их сигнатуры и типы. Классы-протоколы без этого декоратора нельзя использовать в качестве второго аргумента isinstance() или issubclass().

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

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

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

T = TypeVar("T")

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

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

@typing.runtime_checkable

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

Такой протокол можно использовать с isinstance() и issubclass(). Это позволяет выполнять простую структурную проверку, очень похожую на проверки «узкоспециализированных» классов в 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)

При применении к классу, не являющемуся протоколом, этот декоратор вызывает исключение TypeError.

Примечание

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

Примечание

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

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

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

Изменено в версии 3.12: Теперь участники протокола времени выполнения считаются «замороженными» во время выполнения сразу после создания класса. Добавлять атрибуты в протокол времени выполнения с помощью monkey patching по-прежнему можно, но это не повлияет на проверки isinstance() при сопоставлении объектов с протоколом. Подробнее см. в разделе Что нового в Python 3.12.

class typing.TypedDict(dict)

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

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

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

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

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

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

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

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

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

class Definition(TypedDict):
    __schema: str  # mangled to `_Definition__schema`

# OK, functional syntax
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
Definition = TypedDict('Definition', {'__schema': str})  # not mangled

По умолчанию в 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 в качестве значения параметра totality:

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

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

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

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

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

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

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

class Point3D(Point2D):
    z: int

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

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

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

class X(TypedDict):
    x: int

class Y(TypedDict):
    y: int

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

class XY(X, Y): pass  # OK

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

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

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

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

T = TypeVar("T")

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

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

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

__readonly_keys__

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

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

__mutable_keys__

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

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

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

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

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

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

Изменено в версии 3.13: Удалена поддержка создания TypedDict с помощью именованных аргументов.

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

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

Протоколы

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

class typing.SupportsAbs

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

class typing.SupportsBytes

Абстрактный базовый класс с одним абстрактным методом __bytes__.

class typing.SupportsComplex

Абстрактный базовый класс с одним абстрактным методом __complex__.

class typing.SupportsFloat

Абстрактный базовый класс с одним абстрактным методом __float__.

class typing.SupportsIndex

Абстрактный базовый класс с одним абстрактным методом __index__.

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

class typing.SupportsInt

Абстрактный базовый класс с одним абстрактным методом __int__.

class typing.SupportsRound

Абстрактный базовый класс с одним абстрактным методом __round__, ковариантным по типу возвращаемого значения.

Абстрактные базовые классы для работы с вводом-выводом

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 — и никаким другим.

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

См. также

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

Добавлено в версии 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, frozen_default=False, field_specifiers=(), **kwargs)

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

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

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

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

@create_model
class CustomerModel:
    id: int
    name: str

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

@dataclass_transform()
class ModelBase: ...

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

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

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

class ModelBase(metaclass=ModelMeta): ...

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

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

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

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

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

    Указывает, считается ли параметр frozen равным True или False, если вызывающий код его не указал. По умолчанию — False.

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

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

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

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

Имя параметра

Описание

init

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

default

Задаёт значение поля по умолчанию.

default_factory

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

factory

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

kw_only

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

alias

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

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

Дополнительные сведения см. в PEP 681.

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

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

@typing.override

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

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

Например:

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

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

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

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

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

Дополнительные сведения см. в PEP 698.

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

@typing.type_check_only

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

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

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

def fetch_response() -> Response: ...

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

Вспомогательные средства интроспекции

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

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

Часто результат совпадает с obj.__annotations__, но эта функция вносит в словарь аннотаций следующие изменения:

  • Строковые прямые ссылки и объекты ForwardRef обрабатываются путём их вычисления в пространствах имён globalns, localns и (если применимо) параметров типа объекта obj. Если globalns или localns не заданы, соответствующие словари пространств имён выводятся из obj.
  • None заменяется на types.NoneType.
  • Если к obj применён декоратор @no_type_check, возвращается пустой словарь.
  • Если obj является классом C, функция возвращает словарь, объединяющий аннотации базовых классов C с аннотациями самого C. Для этого функция проходит по C.__mro__ и последовательно объединяет словари __annotations__. Аннотации классов, расположенных раньше в порядке разрешения методов, всегда имеют приоритет над аннотациями классов, расположенных позже.
  • Функция рекурсивно заменяет все вхождения Annotated[T, ...] на T, если только для include_extras не задано значение True (дополнительные сведения см. в описании Annotated).

См. также inspect.get_annotations() — низкоуровневую функцию, которая возвращает аннотации более непосредственно.

Примечание

Если какие-либо прямые ссылки в аннотациях obj не удаётся разрешить или они не являются допустимым кодом Python, функция возбуждает исключение, например NameError. Такое может произойти, например, с импортированными псевдонимами типов, содержащими прямые ссылки, или с именами, импортированными под условием if TYPE_CHECKING.

Изменено в версии 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
assert get_origin(Annotated[str, "metadata"]) is Annotated
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.get_protocol_members(tp)

Возвращает множество членов, определённых в Protocol.

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

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

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

typing.is_protocol(tp)

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

Например:

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

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

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

typing.is_typeddict(tp)

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

Например:

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

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

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

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

class typing.ForwardRef

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

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

Примечание

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

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

typing.NoDefault

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

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

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

Константа

typing.TYPE_CHECKING

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

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

if TYPE_CHECKING:
    import expensive_mod

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

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

Примечание

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

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

Устарело начиная с версии 3.9: builtins.dict теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

Устарело начиная с версии 3.9: builtins.list теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

Устарело начиная с версии 3.9: builtins.set теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

Устарело начиная с версии 3.9: builtins.frozenset теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

typing.Tuple

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

tuple и Tuple обрабатываются в системе типов особым образом; дополнительные сведения см. в разделе Annotating tuples.

Устарело начиная с версии 3.9: builtins.tuple теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

class typing.Type(Generic[CT_co])

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

Сведения об использовании type или typing.Type в аннотациях типов см. в разделе The type of class objects.

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

Устарело начиная с версии 3.9: builtins.type теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

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

Устарело начиная с версии 3.9: collections.defaultdict теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

Устарело начиная с версии 3.9: collections.OrderedDict теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

Устарело начиная с версии 3.9: collections.ChainMap теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

Устарело начиная с версии 3.9: collections.Counter теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

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

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

Устарело начиная с версии 3.9: collections.deque теперь поддерживает синтаксис индексации ([]). См. PEP 585 и Generic Alias Type.

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

class typing.Pattern
class typing.Match

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

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

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

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.

Псевдонимы абстрактных базовых классов контейнеров из collections.abc

class typing.AbstractSet(Collection[T_co])

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

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

class typing.ByteString(Sequence[int])

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

Используйте isinstance(obj, collections.abc.Buffer), чтобы во время выполнения проверить, реализует ли obj буферный протокол. В аннотациях типов используйте либо Buffer, либо объединение типов с явным перечислением типов, поддерживаемых вашим кодом (например, bytes | bytearray | memoryview).

Изначально ByteString задумывался как абстрактный класс, который служил бы суперклассом для bytes и bytearray. Однако, поскольку у этого ABC никогда не было методов, знание о том, что объект является экземпляром ByteString, на самом деле ничего полезного об объекте не сообщало. Другие распространённые буферные типы, такие как memoryview, также никогда не считались подтипами ByteString (ни во время выполнения, ни средствами статической проверки типов).

Дополнительные сведения см. в PEP 688.

Устарело начиная с версии 3.9; будет удалено в версии 3.17.

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

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

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

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

class typing.Container(Generic[T_co])

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

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

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

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

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

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

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

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

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

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

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

class typing.MappingView(Sized)

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

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

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

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

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

class typing.MutableSequence(Sequence[T])

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

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

class typing.MutableSet(AbstractSet[T])

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

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

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

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

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

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

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

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

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

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

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

Подробные сведения об использовании collections.abc.Coroutine и typing.Coroutine в аннотациях типов см. в разделе Аннотирование генераторов и сопрограмм.

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

Устарело с версии 3.9: collections.abc.Coroutine теперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.

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

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

Подробные сведения об использовании collections.abc.AsyncGenerator и typing.AsyncGenerator в аннотациях типов см. в разделе Аннотирование генераторов и сопрограмм.

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

Устарело с версии 3.9: collections.abc.AsyncGenerator теперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.

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

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.

Подробные сведения об использовании collections.abc.Generator и typing.Generator в аннотациях типов см. в разделе Аннотирование генераторов и сопрограмм.

Устарело с версии 3.9: collections.abc.Generator теперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.

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

class typing.Hashable

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

Устарело с версии 3.12: Вместо него используйте непосредственно collections.abc.Hashable.

class typing.Reversible(Iterable[T_co])

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

Устарело с версии 3.9: collections.abc.Reversible теперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.

class typing.Sized

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

Устарело с версии 3.12: Вместо него используйте непосредственно collections.abc.Sized.

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

class typing.ContextManager(Generic[T_co, ExitT_co])

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

Первый параметр типа, T_co, обозначает тип, возвращаемый методом __enter__(). Необязательный второй параметр типа, ExitT_co, значение которого по умолчанию равно bool | None, обозначает тип, возвращаемый методом __exit__().

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

Устарело с версии 3.9: contextlib.AbstractContextManager теперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.

Изменено в версии 3.13: Добавлен необязательный второй параметр типа, ExitT_co.

class typing.AsyncContextManager(Generic[T_co, AExitT_co])

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

Первый параметр типа, T_co, обозначает тип, возвращаемый методом __aenter__(). Необязательный второй параметр типа, AExitT_co, значение которого по умолчанию равно bool | None, обозначает тип, возвращаемый методом __aexit__().

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

Устарело с версии 3.9: contextlib.AbstractAsyncContextManager теперь поддерживает индексацию ([]). См. PEP 585 и Обобщённый тип псевдонима.

Изменено в версии 3.13: Добавлен необязательный второй параметр типа, AExitT_co.

Сроки устаревания основных возможностей

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

Возможность

Устарела в версии

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

PEP/issue

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

3.9

Не определено (дополнительные сведения см. в разделе Устаревшие псевдонимы)

PEP 585

typing.ByteString

3.9

3.17

gh-91896

typing.Text

3.11

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

gh-92332

typing.Hashable и typing.Sized

3.12

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

gh-94309

typing.TypeAlias

3.12

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

PEP 695

@typing.no_type_check_decorator

3.13

3.15

gh-106309

typing.AnyStr

3.13

3.18

gh-105578

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

Spec-Zone.ru

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