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

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

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

Примечание

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


Этот модуль обеспечивает поддержку подсказок по набору текста во время выполнения. Исходную спецификацию системы ввода смотрите в разделе PEP 484. Упрощенное введение в подсказки по набору текста смотрите в разделе PEP 483.

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

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

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

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

Краткое описание устаревших функций и график их выхода из строя приведены в разделе Deprecation Timeline of Major Features.

См.также

«Typing cheat sheet»

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

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

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

«Static Typing with Python»

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

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

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

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

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

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

    Представляем Protocol и декоратор @runtime_checkable

  • PEP 585: Введите Общие Подсказки В Стандартных Коллекциях

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

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

    Представляем Literal

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

    Представляем TypedDict

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

    Представляем Final и декоратор @final

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

    Представляем Annotated

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

    *Представляем * types.UnionType и возможность использовать двоичный оператор or | для обозначения union of types

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

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

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

    Представляем TypeAlias

  • PEP 646: Вариативные обобщения

    Представляем TypeVarTuple

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

    Представляем TypeGuard

  • PEP 655: Помечает отдельные элементы Type dict как необходимые или потенциально отсутствующие

    Представляем Required и NotRequired

  • PEP 673: Самостоятельный тип

    Представляем Self

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

    Представляем LiteralString

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

    Представляем декоратора @dataclass_transform


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

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

Vector = list[float]

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

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

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

from collections.abc import Sequence

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

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

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

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

from typing import TypeAlias

Vector: TypeAlias = list[float]

Новый тип

Используйте помощник NewType для создания различных типов:

from typing import NewType

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

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

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

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

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

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

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

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

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

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

from typing import NewType

UserId = NewType('UserId', int)

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

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

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

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

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

Примечание

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

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

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

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

Изменено в версии 3.11: Производительность вызова NewType была восстановлена до прежнего уровня в Python 3.9.

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

Функции или другие объекты callable могут быть аннотированы с помощью 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

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

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

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

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

Callable не может выражать сложные сигнатуры, такие как функции, которые принимают переменное число аргументов, overloaded functions или функции, которые имеют параметры только для ключевых слов. Однако эти сигнатуры могут быть выражены путем определения класса 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: ...

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

from collections.abc import Sequence
from typing import TypeVar

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

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

Кортежи аннотаций

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

from collections.abc import Mapping

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

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

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

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

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

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

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

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

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

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

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

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

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

Переменная, помеченная как C, может принимать значение типа C. Напротив, переменная, помеченная как type[C] (или typing.Type[C]), может принимать значения, которые сами по себе являются классами - в частности, она будет принимать class object из 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, type variables, и объединения любого из этих типов. Например:

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, которое является корнем metaclass hierarchy в Python.

Определяемые пользователем универсальные типы

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

from typing import TypeVar, Generic
from logging import Logger

T = TypeVar('T')

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

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

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

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

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

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

from collections.abc import Iterable

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

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

from typing import TypeVar, Generic, Sequence

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

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

Каждый аргумент переменной типа Generic должен быть разным. Таким образом, это недопустимо:

from typing import TypeVar, Generic
...

T = TypeVar('T')

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

Вы можете использовать множественное наследование с помощью Generic:

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

T = TypeVar('T')

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

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

from collections.abc import Mapping
from typing import TypeVar

T = TypeVar('T')

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

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

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

from collections.abc import Iterable

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

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

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

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

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

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

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

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

>>> from typing import Generic, ParamSpec, TypeVar

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

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

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

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

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

Изменено в версии 3.10: Generic теперь можно параметризовать с помощью выражений параметров. Более подробную информацию смотрите в ParamSpec и PEP 612.

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

Тип 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

A constrained type variable.

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

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

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

Например:

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

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

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

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

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

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

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

Пример:

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

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

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

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

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

typing.Never

bottom type - тип, у которого нет членов.

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

from typing import Never

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

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

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

typing.NoReturn

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

Например:

from typing import NoReturn

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

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

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

typing.Self

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

Например:

from typing import Self, reveal_type

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

class SubclassOfFoo(Foo): pass

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

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

from typing import TypeVar

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

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

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

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

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

  • Аннотирование метода __enter__(), который возвращает self.

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

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

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

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

typing.TypeAlias

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

Например:

from typing import TypeAlias

Factors: TypeAlias = list[int]

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

from typing import Generic, TypeAlias, TypeVar

T = TypeVar("T")

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

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

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

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

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

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

typing.Union

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

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

  • Аргументы должны быть типами, и их должен быть хотя бы один.

  • Объединения союзов сглаживаются, например:

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

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

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

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

  • Вы не можете написать Union[X][Y].

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

Изменено в версии 3.10: Союзы теперь можно записывать как X | Y. Смотрите union type expressions.

typing.Optional

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

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

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

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

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

Изменено в версии 3.10: Необязательный теперь может быть записан как X | None. Смотрите union type expressions.

typing.Concatenate

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

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

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

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

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

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

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

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

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

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

См.также

typing.Literal

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

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

Например:

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

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

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

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

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

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

typing.ClassVar

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

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

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

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

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

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

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

typing.Final

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

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

Например:

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

class Connection:
    TIMEOUT: Final[int] = 10

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

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

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

typing.Required

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

В основном это полезно для ввода total=False. Более подробную информацию смотрите в TypedDict и PEP 655.

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

typing.NotRequired

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

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

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

typing.Annotated

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

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

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

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

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

Annotated[<type>, <metadata>]

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

@dataclass
class ValueRange:
    lo: int
    hi: int

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

Подробные сведения о синтаксисе:

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

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

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

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

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

  • Порядок элементов метаданных сохраняется и имеет значение для проверки на равенство:

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

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

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

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

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

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

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

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

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

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

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

См.также

PEP 593 - Гибкие аннотации к функциям и переменным

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

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

typing.TypeGuard

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

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

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

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

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

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

  1. Возвращаемое значение является логическим.

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

Например:

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

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

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

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

Примечание

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

TypeGuard также работает с переменными типа. Более подробную информацию смотрите в PEP 647.

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

typing.Unpack

Оператор ввода для концептуальной пометки объекта как распакованного.

Например, использование оператора распаковки * для type variable tuple эквивалентно использованию Unpack для обозначения переменной типа tuple как распакованной:

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

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

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

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

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

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

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

class typing.Generic

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

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

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

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

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

def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
    try:
        return mapping[key]
    except KeyError:
        return default
class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False)

Введите переменную.

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

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

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

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


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


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

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

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

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

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

class StringSubclass(str):
    pass

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

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

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

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

Однако использование переменной типа constrained означает, что 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__

Был ли тип var помечен как ковариантный.

__contravariant__

Был ли тип var помечен как контравариантный.

__bound__

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

__constraints__

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

class typing.TypeVarTuple(name)

Введите переменную tuple. Специализированная форма type variable, которая позволяет использовать вариативные обобщения.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

__name__

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

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

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

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

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

P = ParamSpec('P')

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

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

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

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

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

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

Без ParamSpec Самым простым способом аннотирования этого ранее было использование TypeVar с привязкой Callable[..., Any]. Однако это вызывает две проблемы:

  1. Средство проверки типов не может проверить ввод с помощью функции inner, потому что *args и **kwargs должны быть введены Any.

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

args
kwargs

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

__name__

Название спецификации параметра.

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

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

Примечание

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

См.также

typing.ParamSpecArgs
typing.ParamSpecKwargs

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

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

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

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

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

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

class typing.NamedTuple

Напечатанная версия collections.namedtuple().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.NewType(name, tp)

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

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

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

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

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

__name__

Название нового типа.

__supertype__

Тип, на котором основан новый тип.

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

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

class typing.Protocol(Generic)

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

Классы протоколов определяются следующим образом:

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

Такие классы в основном используются со статическими средствами проверки типов, которые распознают структурные подтипы (статическая утиная типизация), например:

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

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

func(C())  # Passes static type check

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

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

T = TypeVar("T")

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

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

@typing.runtime_checkable

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

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

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

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

@runtime_checkable
class Named(Protocol):
    name: str

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

Примечание

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

Примечание

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

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

class typing.TypedDict(dict)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Отдельные клавиши a total=False TypedDict могут быть помечены как необходимые с помощью Required:

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

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

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

class Point3D(Point2D):
    z: int

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

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

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

class X(TypedDict):
    x: int

class Y(TypedDict):
    y: int

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

class XY(X, Y): pass  # OK

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

Значение TypedDict может быть общим:

T = TypeVar("T")

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

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

__total__

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

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

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

__required_keys__

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

__optional_keys__

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

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

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

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

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

Примечание

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

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

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

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

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

Протоколы

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

class typing.SupportsAbs

ABC с одним абстрактным методом __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

ABC с одним абстрактным методом __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, и никаким другим.

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

См.также

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

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

typing.reveal_type(obj, /)

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

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

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

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

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

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

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

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

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

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

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

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

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

T = TypeVar("T")

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

@create_model
class CustomerModel:
    id: int
    name: str

В базовом классе:

@dataclass_transform()
class ModelBase: ...

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

В метаклассе:

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

class ModelBase(metaclass=ModelMeta): ...

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

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

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

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

Parameters:
  • eq_default (bool) – Указывает, принимается ли значение параметра eq равным True или False, если он опущен вызывающей стороной. По умолчанию используется значение True.

  • order_default (bool) – Указывает, принимается ли значение параметра order равным True или False, если он опущен вызывающей стороной. По умолчанию используется значение False.

  • kw_only_default (bool) – Указывает, принимается ли значение параметра kw_only равным True или False, если он опущен вызывающей стороной. По умолчанию используется значение False.

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

  • **kwargs (Any) – Принимаются произвольные другие аргументы ключевого слова, чтобы обеспечить возможность будущих расширений.

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

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

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

Описание

init

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

default

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

default_factory

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

factory

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

kw_only

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

alias

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

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

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

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

@typing.overload

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

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

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

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

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

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

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

typing.get_overloads(func)

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

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

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

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

typing.clear_overloads()

Удалите все зарегистрированные перегрузки во внутреннем реестре.

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

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

@typing.final

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

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

Например:

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

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

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

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

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

@typing.no_type_check

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

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

@no_type_check изменяет оформленный объект на месте.

@typing.no_type_check_decorator

Декоратор, чтобы придать другому декоратору эффект no_type_check().

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

@typing.type_check_only

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

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

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

def fetch_response() -> Response: ...

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

Помощники в самоанализе

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

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

Это часто совпадает с obj.__annotations__. Кроме того, прямые ссылки, закодированные в виде строковых литералов, обрабатываются путем их вычисления в пространствах имен globals и locals. Для класса C верните словарь, созданный путем объединения всех __annotations__ и C.__mro__ в обратном порядке.

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

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

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

Примечание

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

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

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

typing.get_origin(tp)

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

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

Примеры:

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

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

typing.get_args(tp)

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

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

Примеры:

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

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

typing.is_typeddict(tp)

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

Например:

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

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

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

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

class typing.ForwardRef

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

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

Примечание

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

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

Постоянный

typing.TYPE_CHECKING

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

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

if TYPE_CHECKING:
    import expensive_mod

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

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

Примечание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

typing.Tuple

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

tuple и Tuple имеют особый регистр в системе типов; более подробную информацию смотрите в Кортежи аннотаций.

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

class typing.Type(Generic[CT_co])

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.Pattern
class typing.Match

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

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

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

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

class typing.Text

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

Text используется для указания прямого пути, совместимого с кодом на Python 2: в Python 2 Text является псевдонимом для unicode.

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

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

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

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

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

class typing.AbstractSet(Collection[T_co])

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

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

class typing.ByteString(Sequence[int])

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

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

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

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

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

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

class typing.Container(Generic[T_co])

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.MappingView(Sized)

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

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

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

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

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

class typing.MutableSequence(Sequence[T])

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

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

class typing.MutableSet(AbstractSet[T])

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.AsyncIterable(Generic[T_co])

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

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

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

class typing.AsyncIterator(AsyncIterable[T_co])

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

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

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

class typing.Awaitable(Generic[T_co])

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

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

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

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

class typing.Iterable(Generic[T_co])

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

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

class typing.Iterator(Iterable[T_co])

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

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

typing.Callable

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class typing.Hashable

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

class typing.Reversible(Iterable[T_co])

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

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

class typing.Sized

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

Псевдонимы contextlib Азбука

class typing.ContextManager(Generic[T_co])

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

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

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

class typing.AsyncContextManager(Generic[T_co])

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

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

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

Временная шкала устаревания основных функций

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

Особенность

Устарел в

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

ОПТОСОЗ/проблема

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

3.8

3.13

bpo-38291

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

3.9

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

PEP 585

typing.ByteString

3.9

3.14

gh-91896

typing.Text

3.11

Нерешительный

gh-92332

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