typing — Поддержка подсказок типов
Новое в версии 3.5.
Исходный код: Lib/typing.py
Примечание
Интерпретатор Python не проверяет аннотации типов функций и переменных. Их могут использовать сторонние инструменты, такие как проверяющие типы, среды разработки, линтеры и т. д.
Этот модуль предоставляет поддержку подсказок типов во время выполнения. Для исходной спецификации системы типов см. PEP 484. Для упрощенного введения в подсказки типов см. PEP 483.
Функция ниже принимает и возвращает строку и аннотирована следующим образом:
def greeting(name: str) -> str:
return 'Hello ' + name
В функции greeting, аргумент name должен иметь тип str, а тип возвращаемого значения str. В качестве аргументов принимаются подтипы.
В модуль typing часто добавляются новые возможности. Пакет typing_extensions предоставляет обратные порты этих новых возможностей для более старых версий Python.
Подробное описание устаревших функций и график устаревания см. в разделе График устаревания основных функций.
См. также
- “Справочник по типу”
-
Краткий обзор подсказок типов (размещен в документации mypy).
- Раздел “Справочник по системе типов” документации mypy
-
Система типов Python стандартизована через PEP, поэтому данная справка в общих чертах должна быть применима к большинству проверяющих типов Python. (Некоторые части могут быть специфичны для mypy.)
- “Статическая типизация с Python”
-
Независимая от проверяющего инструменты документация, написанная сообществом, описывающая функции системы типов, полезные инструменты для работы с типами и лучшие практики для работы с типами.
Соответствующие PEP
После первоначального введения подсказок типов в PEP 484 и PEP 483, ряд PEP изменили и расширили структуру Python для аннотаций типов:
Полный список PEP
-
- PEP 544: Протоколы: Структурное подтипирование (статическое динамическое типирование)
-
Введение
Protocolи декоратора@runtime_checkable
-
- PEP 585: Подсказки типов дженериков в стандартных коллекциях
-
Введение
types.GenericAliasи возможность использования классов стандартной библиотеки в качестве типов дженериков
-
-
PEP 604: Allow writing union types as X | Y -
Введение
types.UnionTypeи возможность использования оператора бинарного или|для обозначения объединения типов
-
-
- PEP 612: Переменные спецификации параметров
-
Введение
ParamSpecиConcatenate
-
- PEP 646: Многоаргументные дженерики
-
Введение
TypeVarTuple
-
- PEP 655: Отмечание отдельных элементов TypedDict как обязательных или потенциально отсутствующих
-
Введение
RequiredиNotRequired
-
- 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.
Аннотирование вызываемых объектов
Функции – или другие вызываемые объекты – могут быть аннотированы с помощью collections.abc.Callable или typing.Callable. Callable[[int], str] обозначает функцию, которая принимает один параметр типа int и возвращает str.
Например:
from collections.abc import Callable, Awaitable
def feeder(get_next_item: Callable[[], str]) -> None:
... # Body
def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
... # Body
async def on_update(value: str) -> None:
... # Body
callback: Callable[[str], Awaitable[None]] = on_update
Синтаксис подписки всегда должен использоваться ровно с двумя значениями: списком аргументов и типом возвращаемого значения. Список аргументов должен быть списком типов, ParamSpec, Concatenate или многоточие. Тип возвращаемого значения должен быть единственным типом.
Если в качестве списка аргументов указано буквальное многоточие ..., это означает, что вызываемый объект с любым произвольным списком параметров будет приемлем:
def concat(x: str, y: str) -> str:
return x + y
x: Callable[..., str]
x = str # OK
x = concat # Also OK
Callable не может выразить сложные сигнатуры, такие как функции, принимающие переменное число аргументов, перегруженные функции или функции с только именованными параметрами. Однако эти сигнатуры могут быть выражены путём определения класса Protocol с методом __call__():
from collections.abc import Iterable
from typing import Protocol
class Combiner(Protocol):
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...
def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
for item in data:
...
def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
...
batch_proc([], good_cb) # OK
batch_proc([], bad_cb) # Error! Argument 2 has incompatible type because of
# different name and kind in the callback
Вызываемые объекты, которые принимают другие вызываемые объекты в качестве аргументов, могут указывать, что их типы параметров зависят друг от друга, используя ParamSpec. Кроме того, если такой вызываемый объект добавляет или удаляет аргументы из других вызываемых объектов, используется оператор Concatenate. Они имеют вид Callable[ParamSpecVariable, ReturnType] и Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType] соответственно.
Изменено в версии 3.10: Callable теперь поддерживает ParamSpec и Concatenate. См. PEP 612 для получения более подробной информации.
См. также
Документация по ParamSpec и Concatenate содержит примеры использования в Callable.
Обобщения
Поскольку информация о типе объектов, хранящихся в контейнерах, не может быть статически выведена обобщённым способом, многие классы контейнеров в стандартной библиотеке поддерживают подписку для обозначения ожидаемых типов элементов контейнера.
from collections.abc import Mapping, Sequence
class Employee: ...
# Sequence[Employee] indicates that all elements in the sequence
# must be instances of "Employee".
# Mapping[str, str] indicates that all keys and all values in the mapping
# must be strings.
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
Обобщения могут быть параметризованы, используя фабрику, доступную в typing, под названием TypeVar.
from collections.abc import Sequence
from typing import TypeVar
T = TypeVar('T') # Declare type variable "T"
def first(l: Sequence[T]) -> T: # Function is generic over the TypeVar "T"
return l[0]
Аннотирование кортежей
Для большинства контейнеров в Python система типов предполагает, что все элементы в контейнере будут одного типа. Например:
from collections.abc import Mapping
# Type checker will infer that all elements in ``x`` are meant to be ints
x: list[int] = []
# Type checker error: ``list`` only accepts a single type argument:
y: list[int, str] = [1, 'foo']
# Type checker will infer that all keys in ``z`` are meant to be strings,
# and that all values in ``z`` are meant to be either strings or ints
z: Mapping[str, str | int] = {}
list принимает только один аргумент типа, поэтому проверяющий типов выдаст ошибку для y присвоения выше. Аналогично, Mapping принимает только два аргумента типа: первый указывает тип ключей, а второй указывает тип значений.
В отличие от большинства других контейнеров Python, в стандартном Python-коде кортежи часто содержат элементы, которые не являются всех одного типа. По этой причине кортежи имеют специальное назначение в системе типов Python. tuple принимает любое количество аргументов типа:
# OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int x: tuple[int] = (5,) # OK: ``y`` is assigned to a tuple of length 2; # element 1 is an int, element 2 is a str y: tuple[int, str] = (5, "foo") # Error: the type annotation indicates a tuple of length 1, # but ``z`` has been assigned to a tuple of length 3 z: tuple[int] = (1, 2, 3)
Для обозначения кортежа, который может иметь любую длину, и в котором все элементы одного типа T, используйте tuple[T, ...]. Для обозначения пустого кортежа используйте tuple[()]. Использование простого tuple в качестве аннотации эквивалентно использованию tuple[Any, ...]:
x: tuple[int, ...] = (1, 2)
# These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
x = (1, 2, 3)
x = ()
# This reassignment is an error: all elements in ``x`` must be ints
x = ("foo", "bar")
# ``y`` can only ever be assigned to an empty tuple
y: tuple[()] = ()
z: tuple = ("foo", "bar")
# These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
z = (1, 2, 3)
z = ()
Тип объектов класса
Переменная, аннотированная с C может принять значение типа C. В отличие от этого, переменная, аннотированная type[C] (или typing.Type[C]) может принять значения, которые являются сами классами – конкретно, это примет объект класса C. Например:
a = 3 # Has type ``int`` b = int # Has type ``type[int]`` c = type(a) # Also has type ``type[int]``
Обратите внимание, что type[C] является ковариативным:
class User: ...
class ProUser(User): ...
class TeamUser(User): ...
def make_new_user(user_class: type[User]) -> User:
# ...
return user_class()
make_new_user(User) # OK
make_new_user(ProUser) # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser) # Still fine
make_new_user(User()) # Error: expected ``type[User]`` but got ``User``
make_new_user(int) # Error: ``type[int]`` is not a subtype of ``type[User]``
Единственные допустимые параметры для type – это классы, Any, переменные типа и объединения любого из этих типов. Например:
def new_non_team_user(user_class: type[BasicUser | ProUser]): ...
new_non_team_user(BasicUser) # OK
new_non_team_user(ProUser) # OK
new_non_team_user(TeamUser) # Error: ``type[TeamUser]`` is not a subtype
# of ``type[BasicUser | ProUser]``
new_non_team_user(User) # Also an error
type[Any] эквивалентно type, которое является корнем иерархии метаклассов Python.
Пользовательские обобщённые типы
Класс пользователя может быть определён как обобщённый класс.
from typing import TypeVar, Generic
from logging import Logger
T = TypeVar('T')
class LoggedVar(Generic[T]):
def __init__(self, value: T, name: str, logger: Logger) -> None:
self.name = name
self.logger = logger
self.value = value
def set(self, new: T) -> None:
self.log('Set ' + repr(self.value))
self.value = new
def get(self) -> T:
self.log('Get ' + repr(self.value))
return self.value
def log(self, message: str) -> None:
self.logger.info('%s: %s', self.name, message)
Generic[T] как базовый класс определяет, что класс LoggedVar принимает один параметр типа T . Это также делает T допустимым типом в теле класса.
Базовый класс Generic определяет __class_getitem__(), чтобы LoggedVar[T] был допустимым типом:
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
Обобщённый тип может иметь любое количество переменных типа. Все разновидности TypeVar допускаются в качестве параметров обобщённого типа:
from typing import TypeVar, Generic, Sequence
T = TypeVar('T', contravariant=True)
B = TypeVar('B', bound=Sequence[bytes], covariant=True)
S = TypeVar('S', int, str)
class WeirdTrio(Generic[T, B, S]):
...
Каждый аргумент переменной типа для Generic должен быть отличным. Поэтому следующее неверно:
from typing import TypeVar, Generic
...
T = TypeVar('T')
class Pair(Generic[T, T]): # INVALID
...
Можно использовать множественное наследование с Generic:
from collections.abc import Sized
from typing import TypeVar, Generic
T = TypeVar('T')
class LinkedList(Sized, Generic[T]):
...
При наследовании от обобщённых классов некоторые параметры типа могут быть фиксированы:
from collections.abc import Mapping
from typing import TypeVar
T = TypeVar('T')
class MyDict(Mapping[str, T]):
...
В этом случае MyDict имеет один параметр, T.
Использование обобщённого класса без указания параметров типа предполагает Any для каждой позиции. В следующем примере MyIterable не является обобщённым, но неявно наследуется от Iterable[Any]:
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
...
Также поддерживаются псевдонимы обобщённых типов, определённых пользователем. Примеры:
from collections.abc import Iterable
from typing import TypeVar
S = TypeVar('S')
Response = Iterable[S] | int
# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
...
T = TypeVar('T', int, float, complex)
Vec = Iterable[tuple[T, T]]
def inproduct(v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
return sum(x*y for x, y in v)
Изменено в версии 3.7: Generic больше не имеет пользовательского метакласса.
Пользовательские обобщения для выражений параметров также поддерживаются с помощью переменных спецификации параметров в форме Generic[P]. Поведение соответствует описанным выше переменным типов, поскольку модуль typing обрабатывает переменные спецификации параметров как специализированную переменную типа. Единственное исключение из этого заключается в том, что список типов может быть использован для подстановки ParamSpec:
>>> from typing import Generic, ParamSpec, TypeVar
>>> T = TypeVar('T')
>>> P = ParamSpec('P')
>>> class Z(Generic[T, P]): ...
...
>>> Z[int, [dict, float]]
__main__.Z[int, (<class 'dict'>, <class 'float'>)]
Кроме того, обобщение с только одной переменной спецификации параметров будет принимать списки параметров в формах X[[Type1, Type2, ...]] и также X[Type1, Type2, ...] по эстетическим соображениям. Внутренне последнее преобразуется в первое, поэтому следующие выражения эквивалентны:
>>> class X(Generic[P]): ... ... >>> X[int, str] __main__.X[(<class 'int'>, <class 'str'>)] >>> X[[int, str]] __main__.X[(<class 'int'>, <class 'str'>)]
Обратите внимание, что обобщения с ParamSpec могут иметь неверные __parameters__ после подстановки в некоторых случаях, поскольку они предназначены прежде всего для статической проверки типов.
Изменено в версии 3.10: Generic теперь может быть параметризован с помощью выражений параметров. См. ParamSpec и PEP 612 для получения дополнительных сведений.
Пользовательский обобщённый класс может иметь ABC в качестве базовых классов без конфликта метакласса. Обобщённые метаклассы не поддерживаются. Результат параметризации обобщений кешируется, и большинство типов в модуле typing являются хешируемыми и сравниваемыми для равенства.
Тип Any
Особый вид типа — Any. Статический проверяющий типов будет рассматривать каждый тип как совместимый с Any, а Any — как совместимый с любым типом.
Это означает, что можно выполнять любые операции или вызовы методов для значения типа Any и назначать его любой переменной:
from typing import Any
a: Any = None
a = [] # OK
a = 2 # OK
s: str = ''
s = a # OK
def foo(item: Any) -> int:
# Passes type checking; 'item' could be any type,
# and that type might have a 'bar' method
item.bar()
...
Обратите внимание, что проверка типов не выполняется при назначении значения типа Any более точному типу. Например, статический проверяющий типов не выдал ошибку при назначении a к s, даже если s был объявлен как типа str и получает значение int во время выполнения!
Кроме того, все функции без типа возвращаемого значения или типов параметров неявно используют Any:
def legacy_parser(text):
...
return data
# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
...
return data
Это поведение позволяет использовать Any как разрешённый путь, когда вам нужно смешать динамически и статически типизированный код.
Сравните поведение Any с поведением object. Аналогично Any, каждый тип является подтипом object. Однако в отличие от Any, обратное неверно: object не является подтипом каждого другого типа.
Это означает, что когда тип значения равен object, проверяющий типов отклонит почти все операции над ним, а присвоение его переменной (или использование его в качестве значения возврата) более специализированного типа — ошибка типа. Например:
def hash_a(item: object) -> int:
# Fails type checking; an object does not have a 'magic' method.
item.magic()
...
def hash_b(item: Any) -> int:
# Passes type checking
item.magic()
...
# Passes type checking, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")
# Passes type checking, since Any is compatible with all types
hash_b(42)
hash_b("foo")
Используйте object, чтобы указать, что значение может быть любого типа безопасным способом. Используйте Any, чтобы указать, что значение имеет динамический тип.
Номинальное против структурного подтипа
Изначально PEP 484 определил систему статической типизации Python, используя номинальное подтипирование. Это означает, что класс A разрешён там, где ожидается класс B тогда и только тогда, когда A является подклассом B.
Это требование ранее также применялось к абстрактным базовым классам, таким как Iterable. Проблема с этим подходом заключалась в том, что класс должен был быть явно помечен для их поддержки, что не соответствует стилю Python и отличается от того, что обычно делается в идиоматическом динамически типизированном коде Python. Например, это соответствует PEP 484:
from collections.abc import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
PEP 544 позволяет решить эту проблему, позволяя пользователям писать код выше без явных базовых классов в определении класса, позволяя Bucket неявно считаться подтипом как Sized, так и Iterable[int] проверяющими статических типов. Это известно как структурное подтипирование (или статическая имитация натуры):
from collections.abc import Iterator, Iterable
class Bucket: # Note: no base classes
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket()) # Passes type check
Кроме того, наследовавшись от специального класса Protocol, пользователь может определить новые пользовательские протоколы, чтобы полностью использовать структурное подтипирование (см. примеры ниже).
Содержание модуля
Модуль typing определяет следующие классы, функции и декораторы.
Специальные примитивы типизации
Специальные типы
Их можно использовать в качестве типов в аннотациях. Они не поддерживают подписку с помощью [].
-
typing.Any -
Специальный тип, указывающий на не ограниченный тип.
Изменено в версии 3.11:
Anyтеперь можно использовать в качестве базового класса. Это может быть полезно для предотвращения ошибок проверки типов с классами, которые могут быть совместимы с любым типом или являются высокодинамичными.
-
typing.AnyStr -
Переменная ограниченная переменная типа.
Определение:
AnyStr = TypeVar('AnyStr', str, bytes)AnyStrпредназначен для использования в функциях, которые могут принимать аргументы типаstrилиbytes, но не могут допускать их смешение.Например:
def concat(a: AnyStr, b: AnyStr) -> AnyStr: return a + b concat("foo", "bar") # OK, output has type 'str' concat(b"foo", b"bar") # OK, output has type 'bytes' concat("foo", b"bar") # Error, cannot mix str and bytesОбратите внимание, что, несмотря на свое название,
AnyStrне имеет ничего общего с типомAny, а также не означает «любой строковый тип». В частности,AnyStrиstr | bytesотличаются друг от друга и имеют разные области применения:# Invalid use of AnyStr: # The type variable is used only once in the function signature, # so cannot be "solved" by the type checker def greet_bad(cond: bool) -> AnyStr: return "hi there!" if cond else b"greetings!" # The better way of annotating this function: def greet_proper(cond: bool) -> str | bytes: return "hi there!" if cond else b"greetings!"
-
typing.LiteralString -
Специальный тип, включающий только строковые литералы.
Любой строковый литерал совместим с
LiteralString, как и другойLiteralString. Однако объект, типизированный как толькоstr, не совместим. Строка, созданная путем комбинированияLiteralString-типизированных объектов, также принимается в качествеLiteralString.Пример:
def run_query(sql: LiteralString) -> None: ... def caller(arbitrary_string: str, literal_string: LiteralString) -> None: run_query("SELECT * FROM students") # OK run_query(literal_string) # OK run_query("SELECT * FROM " + literal_string) # OK run_query(arbitrary_string) # type checker error run_query( # type checker error f"SELECT * FROM students WHERE name = {arbitrary_string}" )LiteralStringполезен для чувствительных API, где произвольные строки, сгенерированные пользователем, могут вызвать проблемы. Например, два указанных выше случая, которые генерируют ошибки проверки типов, могут быть уязвимы к атакам типа SQL-инъекции.См. PEP 675 для получения дополнительной информации.
Добавлен в версии 3.11.
-
typing.Never -
Тип «нижнего уровня» (bottom type), тип, у которого нет элементов.
Его можно использовать для определения функции, которая никогда не должна вызываться, или функции, которая никогда не возвращает значение:
from typing import Never def never_call_me(arg: Never) -> None: pass def int_or_str(arg: int | str) -> None: never_call_me(arg) # type checker error match arg: case int(): print("It's an int") case str(): print("It's a str") case _: never_call_me(arg) # OK, arg is of type NeverДобавлен в версии 3.11: В более старых версиях Python для выражения той же концепции может использоваться
NoReturn.Neverбыл добавлен для более явного выражения намерений.
-
typing.NoReturn -
Специальный тип, указывающий, что функция никогда не возвращает значение.
Например:
from typing import NoReturn def stop() -> NoReturn: raise RuntimeError('no way')NoReturnтакже может использоваться как тип «нижнего уровня» (bottom type), тип, у которого нет значений. Начиная с Python 3.11, для этой концепции следует использовать типNever. Инструменты проверки типов должны рассматривать эти два типа эквивалентными.Добавлен в версии 3.5.4.
Добавлен в версии 3.6.2.
-
typing.Self -
Специальный тип для представления текущего вложенного класса.
Например:
from typing import Self, reveal_type class Foo: def return_self(self) -> Self: ... return self class SubclassOfFoo(Foo): pass reveal_type(Foo().return_self()) # Revealed type is "Foo" reveal_type(SubclassOfFoo().return_self()) # Revealed type is "SubclassOfFoo"Эта аннотация семантически эквивалентна следующему, хотя и более лаконична:
from typing import TypeVar Self = TypeVar("Self", bound="Foo") class Foo: def return_self(self: Self) -> Self: ... return selfВ общем случае, если что-то возвращает
self, как в приведенных выше примерах, вы должны использоватьSelfв качестве аннотации возвращаемого значения. ЕслиFoo.return_selfбыла аннотирована как возвращающая"Foo", то проверяющий тип вывел бы, что объект, возвращаемый изSubclassOfFoo.return_self, является типомFoo, а неSubclassOfFoo.Другие распространенные случаи использования:
-
classmethod, которые используются как альтернативные конструкторы и возвращают экземпляры параметраcls. - Аннотация метода
__enter__(), который возвращает self.
Вы не должны использовать
Selfв качестве аннотации возвращаемого значения, если метод не гарантированно возвращает экземпляр подкласса при наследовании от класса:class Eggs: # Self would be an incorrect return annotation here, # as the object returned is always an instance of Eggs, # even in subclasses def returns_eggs(self) -> "Eggs": return Eggs()См. PEP 673 для получения дополнительной информации.
Добавлен в версии 3.11.
-
-
typing.TypeAlias -
Специальная аннотация для явного объявления псевдонима типа.
Например:
from typing import TypeAlias Factors: TypeAlias = list[int]
TypeAliasособенно полезно для аннотирования псевдонимов, использующих прямые ссылки, так как проверяющим типам может быть сложно отличить их от обычных присваиваний переменных:from typing import Generic, TypeAlias, TypeVar T = TypeVar("T") # "Box" does not exist yet, # so we have to use quotes for the forward reference. # Using ``TypeAlias`` tells the type checker that this is a type alias declaration, # not a variable assignment to a string. BoxOfStrings: TypeAlias = "Box[str]" class Box(Generic[T]): @classmethod def make_box_of_strings(cls) -> BoxOfStrings: ...См. PEP 613 для получения дополнительной информации.
Добавлен в версии 3.10.
Специальные формы
Их можно использовать в качестве типов в аннотациях. Все они поддерживают подписку с помощью [], но каждая имеет уникальный синтаксис.
-
typing.Union -
Тип объединения;
Union[X, Y]эквивалентенX | Yи означает либо X, либо Y.Для определения объединения используйте, например,
Union[int, str]или сокращённую записьint | str. Рекомендуется использовать сокращённую запись. Подробности:- Аргументы должны быть типами, и их должно быть как минимум один.
-
Объединения объединений сворачиваются, например:
Union[Union[int, str], float] == Union[int, str, float]
-
Объединения из одного аргумента исчезают, например:
Union[int] == int # The constructor actually returns int
-
Избыточные аргументы пропускаются, например:
Union[int, str, int] == Union[int, str] == int | str
-
При сравнении объединений порядок аргументов игнорируется, например:
Union[int, str] == Union[str, int]
- Нельзя создавать подклассы или экземпляры
Union. - Нельзя писать
Union[X][Y].
Изменено в версии 3.7: Не удалять явные подклассы из объединений во время выполнения.
Изменено в версии 3.10: Объединения теперь можно записывать как
X | Y. См. выражения типа объединения.
-
typing.Optional -
Optional[X]эквивалентенX | None(илиUnion[X, None]).Обратите внимание, что это не то же самое, что необязательный аргумент, который имеет значение по умолчанию. Для необязательного аргумента с значением по умолчанию не требуется квалификатор
Optionalв его аннотации типа только потому, что он необязательный. Например:def foo(arg: int = 0) -> None: ...С другой стороны, если разрешено явное значение
None, использованиеOptionalуместно, независимо от того, является ли аргумент необязательным или нет. Например:def foo(arg: Optional[int] = None) -> None: ...Изменено в версии 3.10: Optional теперь можно записывать как
X | None. См. выражения типа объединения.
-
typing.Concatenate -
Специальная форма для аннотирования функций высшего порядка.
Concatenateможет использоваться совместно с Callable иParamSpecдля аннотирования вызываемого объекта высшего порядка, который добавляет, удаляет или преобразует параметры другого вызываемого объекта. Использование в формеConcatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable].Concatenateв настоящее время допустимо только при использовании в качестве первого аргумента Callable. Последний параметрConcatenateдолжен бытьParamSpecили многоточием (...).Например, для аннотирования декоратора
with_lock, который предоставляетthreading.Lockдекорированной функции,Concatenateможно использовать для указания того, чтоwith_lockожидает вызываемый объект, принимающийLockв качестве первого аргумента и возвращающий вызываемый объект с другим сигнатурой типа. В этом случаеParamSpecуказывает, что типы параметров возвращаемого вызываемого объекта зависят от типов параметров передаваемого вызываемого объекта:from collections.abc import Callable from threading import Lock from typing import Concatenate, ParamSpec, TypeVar P = ParamSpec('P') R = TypeVar('R') # Use this lock to ensure that only one thread is executing a function # at any time. my_lock = Lock() def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: '''A type-safe decorator which provides a lock.''' def inner(*args: P.args, **kwargs: P.kwargs) -> R: # Provide the lock as the first argument. return f(my_lock, *args, **kwargs) return inner @with_lock def sum_threadsafe(lock: Lock, numbers: list[float]) -> float: '''Add a list of numbers together in a thread-safe manner.''' with lock: return sum(numbers) # We don't need to pass in the lock ourselves thanks to the decorator. sum_threadsafe([1.1, 2.2, 3.3])Новое в версии 3.10.
См. также
-
PEP 612 — Переменные спецификации параметров (PEP, который представил
ParamSpecиConcatenate) ParamSpec- Аннотирование вызываемых объектов
-
PEP 612 — Переменные спецификации параметров (PEP, который представил
-
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 checkerLiteral[...]не может быть подклассом. Во время выполнения произвольное значение допускается в качестве аргумента типаLiteral[...], но проверяющие типы могут накладывать ограничения. См. PEP 586 для получения дополнительной информации о литеральных типах.Новое в версии 3.8.
Изменено в версии 3.9.1:
Literalтеперь удаляет дубликаты параметров. Сравнения на равенство объектовLiteralбольше не зависят от порядка. ОбъектыLiteralтеперь будут генерировать исключениеTypeErrorво время сравнения на равенство, если один из их параметров не является хешируемым.
-
typing.ClassVar -
Специальная конструкция типа для маркировки переменных класса.
Как введено в PEP 526, аннотация переменной, заключенная в ClassVar, указывает, что данный атрибут предназначен для использования в качестве переменной класса и не должен устанавливаться для экземпляров этого класса. Использование:
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variableClassVarпринимает только типы и не может быть дальше подписывается.ClassVarне является классом сам по себе и не должен использоваться сisinstance()илиissubclass().ClassVarне изменяет поведение Python во время выполнения, но может использоваться сторонними проверяющими типами. Например, проверяющий типов может пометить следующий код как ошибку:enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OKНовое в версии 3.5.3.
-
typing.Final -
Специальная конструкция типизации для указания конечных имён проверяющим типам.
Конечные имена не могут быть переназначены ни в одном области видимости. Конечные имена, объявленные в областях видимости классов, не могут быть переопределены в подклассах.
Например:
MAX_SIZE: Final = 9000 MAX_SIZE += 1 # Error reported by type checker class Connection: TIMEOUT: Final[int] = 10 class FastConnector(Connection): TIMEOUT = 1 # Error reported by type checkerНет проверки этих свойств во время выполнения. См. PEP 591 для получения дополнительной информации.
Новое в версии 3.8.
-
typing.Annotated -
Специальная форма типизации для добавления метаданных, специфичных для контекста, в аннотацию.
Добавьте метаданные
xк заданному типуTс помощью аннотацииAnnotated[T, x]. Метаданные, добавленные с помощьюAnnotated, могут использоваться инструментами статического анализа или во время выполнения. Во время выполнения метаданные хранятся в атрибуте__metadata__.Если библиотека или инструмент сталкивается с аннотацией
Annotated[T, x]и не имеет специальной логики для метаданных, она должна игнорировать метаданные и просто рассматривать аннотацию какT. Таким образом,Annotatedможет быть полезным для кода, который хочет использовать аннотации в целях, выходящих за рамки системы статической типизации Python.Использование
Annotated[T, x]в качестве аннотации всё ещё позволяет выполнять статическую проверку типовT, так как инструменты проверки типов просто проигнорируют метаданныеx. Таким образом,Annotatedотличается от декоратора@no_type_check, который также может использоваться для добавления аннотаций за пределами области системы типизации, но полностью отключает проверку типов для функции или класса.Ответственность за интерпретацию метаданных лежит на инструменте или библиотеке, столкнувшейся с аннотацией
Annotated. Инструмент или библиотека, столкнувшаяся с типомAnnotated, может просмотреть элементы метаданных, чтобы определить, представляют ли они интерес (например, с использованиемisinstance()).- Annotated[<type>, <metadata>]
Вот пример того, как можно использовать
Annotatedдля добавления метаданных к аннотациям типов, если вы выполняете анализ диапазонов:@dataclass class ValueRange: lo: int hi: int T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)]Подробности синтаксиса:
- Первый аргумент для
Annotatedдолжен быть допустимым типом -
Можно указать несколько элементов метаданных (
Annotatedподдерживает аргументы с переменным числом):@dataclass class ctype: kind: str Annotated[int, ValueRange(3, 10), ctype("char")]Инструменту, использующему аннотации, предстоит решить, разрешено ли клиенту добавлять несколько элементов метаданных к одной аннотации, и как объединять эти аннотации.
-
Annotatedдолжен быть индексирован как минимум двумя аргументами (Annotated[int]недопустимо) -
Порядок элементов метаданных сохраняется и имеет значение для проверок на равенство:
assert Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[ int, ctype("char"), ValueRange(3, 10) ] -
Вложенные типы
Annotatedсглаживаются. Порядок элементов метаданных начинается с самой внутренней аннотации:assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ] -
Дублированные элементы метаданных не удаляются:
assert Annotated[int, ValueRange(3, 10)] != Annotated[ int, ValueRange(3, 10), ValueRange(3, 10) ] -
Annotatedможно использовать со вложенными и обобщенными псевдонимами:@dataclass class MaxLen: value: int T = TypeVar("T") Vec: TypeAlias = Annotated[list[tuple[T, T]], MaxLen(10)] assert Vec[int] == Annotated[list[tuple[int, int]], MaxLen(10)] -
Annotatedнельзя использовать с распакованнымTypeVarTuple:Variadic: TypeAlias = Annotated[*Ts, Ann1] # NOT valid
Это эквивалентно:
Annotated[T1, T2, T3, ..., Ann1]
где
T1,T2, и т. д. –TypeVars. Это будет недопустимо: в Annotated должен быть передан только один тип. -
По умолчанию
get_type_hints()удаляет метаданные из аннотаций. Передайтеinclude_extras=Trueдля сохранения метаданных:>>> from typing import Annotated, get_type_hints >>> def func(x: Annotated[int, "metadata"]) -> None: pass ... >>> get_type_hints(func) {'x': <class 'int'>, 'return': <class 'NoneType'>} >>> get_type_hints(func, include_extras=True) {'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>} -
Во время выполнения метаданные, связанные с типом
Annotated, можно получить через атрибут__metadata__.>>> from typing import Annotated >>> X = Annotated[int, "very", "important", "metadata"] >>> X typing.Annotated[int, 'very', 'important', 'metadata'] >>> X.__metadata__ ('very', 'important', 'metadata')
См. также
- PEP 593 – Гибкие аннотации функций и переменных
-
PEP, представляющий
Annotatedв стандартной библиотеке.
Добавлена в версии 3.9.
-
typing.TypeGuard -
Специальная конструкция типизации для маркировки функций-фильтров типов, определенных пользователем.
TypeGuardможет использоваться для аннотирования возвращаемого типа пользовательской функции-фильтра типов.TypeGuardпринимает только один аргумент типа. Во время выполнения функции, помеченные таким образом, должны возвращать логическое значение.TypeGuardнаправлен на получение сужения типов – техники, используемой инструментами статической типизации для определения более точного типа выражения в потоке выполнения программы. Обычно сужение типов выполняется путём анализа условного потока кода и применения сужения к блоку кода. Условное выражение в данном случае иногда называют «фильтром типа»:def is_str(val: str | float): # "isinstance" type guard if isinstance(val, str): # Type of ``val`` is narrowed to ``str`` ... else: # Else, type of ``val`` is narrowed to ``float``. ...Иногда удобно использовать пользовательскую булеву функцию в качестве фильтра типов. Такая функция должна использовать
TypeGuard[...]в качестве типа возвращаемого значения, чтобы уведомить инструменты статической типизации об этом намерении.Использование
-> TypeGuardуказывает инструменту статической типизации, что для данной функции:- Возвращаемое значение имеет логический тип.
- Если возвращаемое значение
True, тип её аргумента – тип внутриTypeGuard.
Например:
def is_str_list(val: list[object]) -> TypeGuard[list[str]]: '''Determines whether all objects in the list are strings''' return all(isinstance(x, str) for x in val) def func1(val: list[object]): if is_str_list(val): # Type of ``val`` is narrowed to ``list[str]``. print(" ".join(val)) else: # Type of ``val`` remains as ``list[object]``. print("Not a list of strings!")Если
is_str_listявляется методом класса или экземпляра, то тип вTypeGuardсопоставляется с типом второго параметра послеclsилиself.Короче говоря, форма
def foo(arg: TypeA) -> TypeGuard[TypeB]: ..., означает, что еслиfoo(arg)возвращаетTrue, тоargсужается сTypeAдоTypeB.Примечание
TypeBне обязательно должен быть более узкой формойTypeA– он может быть даже более широкой формой. Основная причина заключается в возможности суженияlist[object]доlist[str], даже если последний не является подтипом первого, так какlistявляется инвариантным. Ответственность за создание безопасных фильтров типов возлагается на пользователя.TypeGuardтакже работает с переменными типов. Смотрите PEP 647 для получения дополнительной информации.Добавлена в версии 3.10.
-
typing.Unpack -
Оператор типизации, концептуально отмечающий объект как распакованный.
Например, использование оператора распаковки
*для кортежа переменной типа эквивалентно использованиюUnpackдля маркировки кортежа переменной типа как распакованного:Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Effectively does: tup: tuple[Unpack[Ts]]Фактически,
Unpackможно использовать взаимозаменяемо с*в контекстеtyping.TypeVarTupleиbuiltins.tupleтипов. Вы могли видетьUnpackв более старых версиях Python, где*нельзя было использовать в определенных местах:# In older versions of Python, TypeVarTuple and Unpack # are located in the `typing_extensions` backports package. from typing_extensions import TypeVarTuple, Unpack Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Syntax error on Python <= 3.10! tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatibleДобавлена в версии 3.11.
Создание универсальных типов
Следующие классы не должны использоваться напрямую в качестве аннотаций. Они предназначены для создания универсальных типов.
-
class typing.Generic -
Абстрактный базовый класс для универсальных типов.
Универсальный тип обычно объявляется путем наследования от экземпляра этого класса с одной или несколькими переменными типа. Например, универсальный тип отображения может быть определен следующим образом:
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.Этот класс затем может использоваться следующим образом:
X = TypeVar('X') Y = TypeVar('Y') def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return default
-
class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False) -
Переменная типа.
Использование:
T = TypeVar('T') # Can be anything S = TypeVar('S', bound=str) # Can be any subtype of str A = TypeVar('A', str, bytes) # Must be exactly str or bytesПеременные типа в первую очередь предназначены для статических проверочных систем типов. Они служат параметрами для универсальных типов, а также для определения универсальных функций и псевдонимов типов. См.
Genericдля получения дополнительной информации об универсальных типах. Универсальные функции работают следующим образом:def repeat(x: T, n: int) -> Sequence[T]: """Return a list containing n references to x.""" return [x]*n def print_capitalized(x: S) -> S: """Print x capitalized, and return x.""" print(x.capitalize()) return x def concatenate(x: A, y: A) -> A: """Add two strings or bytes objects together.""" return x + yОбратите внимание, что переменные типа могут быть связаны, ограничены или ни тем, ни другим, но не могут быть одновременно связаны и ограничены.
Переменные типа могут быть помечены как ковариативные или контравариативные, передавая
covariant=Trueилиcontravariant=True. См. PEP 484 для получения более подробной информации. По умолчанию переменные типа инвариантны.Связанные переменные типа и ограниченные переменные типа имеют разную семантику по нескольким важным параметрам. Использование связанной переменной типа означает, что
TypeVarбудет решено с использованием наиболее специфичного типа:x = print_capitalized('a string') reveal_type(x) # revealed type is str class StringSubclass(str): pass y = print_capitalized(StringSubclass('another string')) reveal_type(y) # revealed type is StringSubclass z = print_capitalized(45) # error: int is not a subtype of strПеременные типа могут быть связаны с конкретными типами, абстрактными типами (ABC или протоколами), а также с объединением типов:
U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ methodИспользование ограниченной переменной типа, однако, означает, что
TypeVarможет быть решена только как один из указанных ограничений:a = concatenate('one', 'two') reveal_type(a) # revealed type is str b = concatenate(StringSubclass('one'), StringSubclass('two')) reveal_type(b) # revealed type is str, despite StringSubclass being passed in c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not bothВо время выполнения
isinstance(x, T)будет вызватьTypeError.-
__name__ -
Имя переменной типа.
-
__covariant__ -
Указывает, помечена ли переменная типа как ковариативная.
-
__contravariant__ -
Указывает, помечена ли переменная типа как контравариативная.
-
__bound__ -
Связь переменной типа, если она есть.
-
__constraints__ -
Кортеж, содержащий ограничения переменной типа, если они есть.
-
-
class typing.TypeVarTuple(name) -
Кортеж переменных типа. Специализированная форма переменной типа, которая позволяет создавать вариадические универсалы.
Использование:
T = TypeVar("T") Ts = TypeVarTuple("Ts") def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])Обычная переменная типа позволяет параметризацию одним типом. В отличие от этого, кортеж переменных типа позволяет параметризацию произвольным количеством типов, действуя как произвольное количество переменных типа, заключенных в кортеж. Например:
# T is bound to int, Ts is bound to () # Return value is (1,), which has type tuple[int] move_first_element_to_last(tup=(1,)) # T is bound to int, Ts is bound to (str,) # Return value is ('spam', 1), which has type tuple[str, int] move_first_element_to_last(tup=(1, 'spam')) # T is bound to int, Ts is bound to (str, float) # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int] move_first_element_to_last(tup=(1, 'spam', 3.0)) # This fails to type check (and fails at runtime) # because tuple[()] is not compatible with tuple[T, *Ts] # (at least one element is required) move_first_element_to_last(tup=())Обратите внимание на использование оператора распаковки
*вtuple[T, *Ts]. Концептуально, вы можете рассматриватьTsкак кортеж переменных типа(T1, T2, ...).tuple[T, *Ts]затем станетtuple[T, *(T1, T2, ...)], что эквивалентноtuple[T, T1, T2, ...]. (Обратите внимание, что в более ранних версиях Python это могло быть записано с использованиемUnpackвместо, так какUnpack[Ts].)Кортежи переменных типа всегда должны распаковываться. Это помогает отличить кортежи переменных типа от обычных переменных типа:
x: Ts # Not valid x: tuple[Ts] # Not valid x: tuple[*Ts] # The correct way to do it
Кортежи переменных типа можно использовать в тех же контекстах, что и обычные переменные типа. Например, в определениях классов, аргументах и типах возвращаемых значений:
Shape = TypeVarTuple("Shape") class Array(Generic[*Shape]): def __getitem__(self, key: tuple[*Shape]) -> float: ... def __abs__(self) -> "Array[*Shape]": ... def get_shape(self) -> tuple[*Shape]: ...Кортежи переменных типа могут быть успешно объединены с обычными переменными типа:
DType = TypeVar('DType') Shape = TypeVarTuple('Shape') class Array(Generic[DType, *Shape]): # This is fine pass class Array2(Generic[*Shape, DType]): # This would also be fine pass class Height: ... class Width: ... float_array_1d: Array[float, Height] = Array() # Totally fine int_array_2d: Array[int, Height, Width] = Array() # Yup, fine tooОднако обратите внимание, что не более одного кортежа переменных типа может появиться в одном списке аргументов типа или параметров типа:
x: tuple[*Ts, *Ts] # Not valid class Array(Generic[*Shape, *Shape]): # Not valid passНаконец, распакованный кортеж переменных типа может использоваться в качестве аннотации типа
*args:def call_soon( callback: Callable[[*Ts], None], *args: *Ts ) -> None: ... callback(*args)В отличие от нераспакованных аннотаций
*args- например,*args: int, которые бы указывали, что все аргументыint-*args: *Tsпозволяет ссылаться на типы отдельных аргументов в*args. Здесь это позволяет гарантировать, что типы*argsпередаваемые вcall_soonсоответствуют типам (позиционных) аргументовcallback.См. PEP 646 для получения дополнительной информации о кортежах переменных типа.
-
__name__ -
Имя кортежа переменной типа.
Введено в версии 3.11.
-
-
class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False) -
Переменная спецификации параметра. Специализированная версия переменных типа.
Использование:
P = ParamSpec('P')Переменные спецификации параметров в основном предназначены для статических проверочных систем типов. Они используются для передачи типов параметров одного вызываемого объекта другому вызываемому объекту – шаблон, часто встречающийся в функциях высшего порядка и декораторах. Они допустимы только при использовании в
Concatenate, или в качестве первого аргументаCallable, или в качестве параметров для пользовательских универсалов. См.Genericдля получения дополнительной информации об универсальных типах.Например, чтобы добавить базовую регистрацию в функцию, можно создать декоратор
add_loggingдля регистрации вызовов функций. Переменная спецификации параметра сообщает системе проверки типов, что вызываемый объект, передаваемый в декоратор, и новый вызываемый объект, возвращаемый им, имеют взаимозависимые параметры типа:from collections.abc import Callable from typing import TypeVar, ParamSpec import logging T = TypeVar('T') P = ParamSpec('P') def add_logging(f: Callable[P, T]) -> Callable[P, T]: '''A type-safe decorator to add logging to a function.''' def inner(*args: P.args, **kwargs: P.kwargs) -> T: logging.info(f'{f.__name__} was called') return f(*args, **kwargs) return inner @add_logging def add_two(x: float, y: float) -> float: '''Add two numbers together.''' return x + yБез
ParamSpec, самый простой способ аннотировать это раньше был использоватьTypeVarсо связаннымCallable[..., Any]. Однако это вызывает две проблемы:- Система проверки типов не может проверить функцию
inner, потому что*argsи**kwargsдолжны иметь типAny. -
cast()может потребоваться в теле декоратораadd_loggingпри возвращении функцииinner, или системе проверки типов нужно сказать игнорироватьreturn inner.
-
args
-
kwargs -
Поскольку
ParamSpecохватывает как позиционные, так и ключевые параметры,P.argsиP.kwargsмогут использоваться для разделенияParamSpecна компоненты.P.argsпредставляет кортеж позиционных параметров в заданном вызове и должен использоваться только для аннотации*args.P.kwargsпредставляет отображение ключевых параметров на их значения в данном вызове и должно использоваться только для аннотации**kwargs. Оба атрибута требуют, чтобы аннотируемый параметр был в области видимости. Во время выполненияP.argsиP.kwargsявляются экземплярами соответственноParamSpecArgsиParamSpecKwargs.
-
__name__ -
Имя спецификации параметра.
Переменные спецификации параметров, созданные с помощью
covariant=Trueилиcontravariant=True, могут использоваться для объявления ковариативных или контравариативных универсальных типов. Аргументboundтакже принимается, аналогичноTypeVar. Однако фактическая семантика этих ключевых слов еще не определена.Введено в версии 3.10.
Примечание
Только переменные спецификации параметров, определенные в глобальной области, могут быть сериализованы.
См. также
-
PEP 612 – Переменные спецификации параметров (PEP, который представил
ParamSpecиConcatenate) Concatenate- Аннотирование вызываемых объектов
- Система проверки типов не может проверить функцию
-
typing.ParamSpecArgs
-
typing.ParamSpecKwargs -
Атрибуты аргументов и ключевых аргументов
ParamSpec. АтрибутP.argsобъектаParamSpecявляется экземпляромParamSpecArgs, а атрибутP.kwargs— экземпляромParamSpecKwargs. Они предназначены для интроспекции во время выполнения и не имеют особого значения для статических проверок типов.Вызов
get_origin()для любого из этих объектов вернёт исходныйParamSpec.>>> from typing import ParamSpec, get_origin >>> P = ParamSpec("P") >>> get_origin(P.args) is P True >>> get_origin(P.kwargs) is P TrueВведено в версии 3.10.
Другие специальные директивы
Эти функции и классы не должны использоваться напрямую в качестве аннотаций. Их назначение — быть строительными блоками для создания и объявления типов.
-
class typing.NamedTuple -
Типизированный аналог
collections.namedtuple().Использование:
class Employee(NamedTuple): name: str id: intЭто эквивалентно:
Employee = collections.namedtuple('Employee', ['name', 'id'])Для присвоения значения по умолчанию полю, его можно задать в теле класса:
class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3Поля со значениями по умолчанию должны следовать за полями без значений по умолчанию.
Получившийся класс имеет дополнительный атрибут
__annotations__, содержащий словарь, сопоставляющий имена полей с их типами. (Имена полей находятся в атрибуте_fields, а значения по умолчанию — в атрибуте_field_defaults, оба из которых являются частью APInamedtuple().)NamedTupleподклассы также могут иметь строки документации и методы:class Employee(NamedTuple): """Represents an employee.""" name: str id: int = 3 def __repr__(self) -> str: return f'<Employee {self.name}, id={self.id}>'NamedTupleподклассы могут быть обобщёнными:class Group(NamedTuple, Generic[T]): key: T group: list[T]Обратная совместимость:
Employee = NamedTuple('Employee', [('name', str), ('id', int)])Изменено в версии 3.6: Добавленв поддержка синтаксиса аннотаций переменных PEP 526.
Изменено в версии 3.6.1: Добавленв поддержка значений по умолчанию, методов и строк документации.
Изменено в версии 3.8: Атрибуты
_field_typesи__annotations__теперь представляют собой обычные словари вместо экземпляровOrderedDict.Изменено в версии 3.9: Удален атрибут
_field_typesв пользу более стандартного атрибута__annotations__, содержащего ту же информацию.Изменено в версии 3.11: Добавлена поддержка обобщённых namedtuple.
-
class typing.NewType(name, tp) -
Вспомогательный класс для создания типов с низкой накладной стоимостью различительных типов.
Статический проверяющий типов рассматривает
NewTypeкак отдельный тип. Однако во время выполнения вызовNewTypeвозвращает свой аргумент без изменений.Использование:
UserId = NewType('UserId', int) # Declare the NewType "UserId" first_user = UserId(1) # "UserId" returns the argument unchanged at runtime-
__module__ -
Модуль, в котором определён новый тип.
-
__name__ -
Имя нового типа.
-
__supertype__ -
Тип, на основе которого создан новый тип.
Введено в версии 3.5.2.
Изменено в версии 3.10:
NewTypeтеперь является классом, а не функцией. -
-
class typing.Protocol(Generic) -
Базовый класс для классов-протоколов.
Классы-протоколы определяются так:
class Proto(Protocol): def meth(self) -> int: ...В основном такие классы используются с проверками статических типов, которые распознают структурное подтипирование (статическое «пёстрое наследование»), например:
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type checkПодробнее см. PEP 544. Классы-протоколы, декорированные
runtime_checkable()(описанные позже), действуют как простые протоколы времени выполнения, проверяющие только наличие заданных атрибутов, игнорируя их сигнатуры типов.Классы-протоколы могут быть обобщёнными, например:
T = TypeVar("T") class GenProto(Protocol[T]): def meth(self) -> T: ...Введено в версии 3.8.
-
@typing.runtime_checkable -
Отметить класс-протокол как протокол времени выполнения.
Такой протокол можно использовать с
isinstance()иissubclass(). При применении к классу, не являющемуся протоколом, это вызываетTypeError. Это позволяет выполнять простую структурную проверку, очень похожую на «одного трюка» вcollections.abc, например,Iterable. Например:@runtime_checkable class Closable(Protocol): def close(self): ... assert isinstance(open('/some/file'), Closable) @runtime_checkable class Named(Protocol): name: str import threading assert isinstance(threading.Thread(name='Bob'), Named)Примечание
runtime_checkable()будет проверять только наличие необходимых методов или атрибутов, а не их сигнатуры типов или типы. Например,ssl.SSLObject— это класс, поэтому он проходит проверкуissubclass()на Callable. Однако методssl.SSLObject.__init__существует только для повышенияTypeErrorс более информативным сообщением, поэтому вызвать (создать экземпляр)ssl.SSLObjectневозможно.Примечание
Проверка
isinstance()на протокол, отмеченный как протокол времени выполнения, может быть неожиданно медленной по сравнению с проверкойisinstance()на класс, не являющийся протоколом. Рассмотрите альтернативные методы, такие как вызовыhasattr()для структурных проверок в чувствительном к производительности коде.Введено в версии 3.8.
-
class typing.TypedDict(dict) -
Специальная конструкция для добавления подсказок типов к словарю. Во время выполнения это обычный
dict.TypedDictобъявляет тип словаря, который ожидает, что все его экземпляры будут иметь определённый набор ключей, где каждый ключ связан со значением согласованного типа. Это ожидание не проверяется во время выполнения, но только проверяется средствами проверки типов. Пример использования:class Point2D(TypedDict): x: int y: int label: str a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')Для возможности использования этой функции с более старыми версиями Python, которые не поддерживают PEP 526,
TypedDictподдерживает два дополнительных эквивалентных синтаксических формата:-
Использование литерального
dictв качестве второго аргумента:Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) -
Использование ключевых аргументов:
Point2D = TypedDict('Point2D', x=int, y=int, label=str)
Устарело начиная с версии 3.11, будет удалено в версии 3.13: Синтаксис ключевых аргументов устарел в 3.11 и будет удалён в 3.13. Он также может быть не поддерживаемым средствами статической проверки типов.
Функциональный синтаксис также должен использоваться, когда любой из ключей не является допустимым идентификатором, например, потому что это ключевые слова или содержат дефисы. Пример:
# raises SyntaxError class Point2D(TypedDict): in: int # 'in' is a keyword x-y: int # name with hyphens # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})По умолчанию все ключи должны быть присутствовать в
TypedDict. Можно отметить отдельные ключи как необязательные, используяNotRequired:class Point2D(TypedDict): x: int y: int label: NotRequired[str] # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})Это означает, что
Point2DTypedDictможет иметь ключlabelопущенным.Также можно отметить все ключи как необязательные по умолчанию, указав значение
False:class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)Это означает, что у
Point2DTypedDictмогут быть опущены любые ключи. Средства проверки типов должны поддерживать только литеральноеFalseилиTrueв качестве значения аргументаtotal.True— значение по умолчанию, которое делает все элементы, определённые в теле класса, обязательными.Отдельные ключи
total=FalseTypedDictможно отметить как обязательные, используя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: intPoint3Dимеет три элемента:x,yиz. Это эквивалентно следующему определению:class Point3D(TypedDict): x: int y: int z: intTypedDictне может наследоваться от класса, который не является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 TypeErrorTypedDictможет быть обобщённым:T = TypeVar("T") class Group(TypedDict, Generic[T]): key: T group: list[T]TypedDictможно получить доступ через словари аннотаций (см. Рекомендации по наилучшей практике использования аннотаций для получения дополнительной информации о наилучшей практике использования аннотаций),__total__,__required_keys__и__optional_keys__.-
__total__ -
Point2D.__total__возвращает значение аргументаtotal. Пример:>>> from typing import TypedDict >>> class Point2D(TypedDict): pass >>> Point2D.__total__ True >>> class Point2D(TypedDict, total=False): pass >>> Point2D.__total__ False >>> class Point3D(Point2D): pass >>> Point3D.__total__ True
Этот атрибут отражает только значение аргумента
totalдля текущего классаTypedDict, а не является ли класс семантически полным. Например,TypedDictс__total__установленным в True может иметь ключи, помеченныеNotRequired, или он может наследоваться от другогоTypedDictсtotal=False. Поэтому для интроспекции лучше использовать__required_keys__и__optional_keys__.
-
__required_keys__ -
Введено в версии 3.9.
-
__optional_keys__ -
Point2D.__required_keys__иPoint2D.__optional_keys__возвращают объектыfrozenset, содержащие обязательные и необязательные ключи соответственно.Ключи, помеченные
Required, всегда будут отображаться в__required_keys__, а ключи, помеченныеNotRequired, всегда будут отображаться в__optional_keys__.Для обратной совместимости с Python 3.10 и ниже также можно использовать наследование для объявления как обязательных, так и необязательных ключей в одном
TypedDict. Для этого объявляетсяTypedDictс одним значением для аргументаtotalи затем наследуется от него в другомTypedDictс другим значением дляtotal:>>> class Point2D(TypedDict, total=False): ... x: int ... y: int ... >>> class Point3D(Point2D): ... z: int ... >>> Point3D.__required_keys__ == frozenset({'z'}) True >>> Point3D.__optional_keys__ == frozenset({'x', 'y'}) TrueВведено в версии 3.9.
Примечание
Если используется
from __future__ import annotationsили если аннотации задаются в виде строк, аннотации не вычисляются при определенииTypedDict. Поэтому динамическая интроспекция, на которой полагаются__required_keys__и__optional_keys__, может работать некорректно, и значения атрибутов могут быть неверными.
См. PEP 589 для получения дополнительных примеров и подробных правил использования
TypedDict.Введено в версии 3.8.
Изменено в версии 3.11: Добавлена поддержка маркировки отдельных ключей как
RequiredилиNotRequired. См. PEP 655.Изменено в версии 3.11: Добавлена поддержка обобщённых
TypedDict. -
Протоколы
Следующие протоколы предоставляются модулем typing. Все они отмечены @runtime_checkable.
-
class typing.SupportsAbs -
ABC с одним абстрактным методом
__abs__, ковариативным по своему возвращаемому типу.
-
class typing.SupportsBytes -
ABC с одним абстрактным методом
__bytes__.
-
class typing.SupportsComplex -
ABC с одним абстрактным методом
__complex__.
-
class typing.SupportsFloat -
ABC с одним абстрактным методом
__float__.
-
class typing.SupportsIndex -
ABC с одним абстрактным методом
__index__.Введено в версии 3.8.
-
class typing.SupportsInt -
ABC с одним абстрактным методом
__int__.
-
class typing.SupportsRound -
ABC с одним абстрактным методом
__round__, ковариативным по своему возвращаемому типу.
ABC для работы с IO
-
class typing.IO -
class typing.TextIO -
class typing.BinaryIO -
Обобщённый тип
IO[AnyStr]и его подклассыTextIO(IO[str])иBinaryIO(IO[bytes])представляют типы потоков ввода-вывода, возвращаемые функциейopen().
Функции и декораторы
-
typing.cast(typ, val) -
Преобразование значения к типу.
Это возвращает значение без изменений. Для статического анализа типов это означает, что возвращаемое значение имеет указанный тип, но во время выполнения мы намеренно ничего не проверяем (мы хотим, чтобы это было максимально быстро).
-
typing.assert_type(val, typ, /) -
Запрос к статическому анализатору типов для подтверждения, что val имеет предполагаемый тип typ.
Во время выполнения это ничего не делает: возвращает первый аргумент без изменений, без проверок или побочных эффектов, независимо от фактического типа аргумента.
Когда статический анализатор типов сталкивается с вызовом
assert_type(), он выдает ошибку, если значение не соответствует указанному типу:def greet(name: str) -> None: assert_type(name, str) # OK, inferred type of `name` is `str` assert_type(name, int) # type checker errorЭта функция полезна для обеспечения того, что понимание сценария статическим анализатором соответствует намерениям разработчика:
def complex_function(arg: object): # Do some complex type-narrowing logic, # after which we hope the inferred type will be `int` ... # Test whether the type checker correctly understands our function assert_type(arg, int)Добавлена в версии 3.11.
-
typing.assert_never(arg, /) -
Запрос к статическому анализатору типов для подтверждения того, что строка кода недостижима.
Пример:
def int_or_str(arg: int | str) -> None: match arg: case int(): print("It's an int") case str(): print("It's a str") case _ as unreachable: assert_never(unreachable)Здесь аннотации позволяют анализатору типов сделать вывод, что последний случай никогда не выполнится, потому что
argявляется либоint, либоstr, и оба варианта покрываются предыдущими случаями.Если анализатор типов обнаруживает, что вызов
assert_never()достижим, он выдаст ошибку. Например, если аннотация типа дляargбыла вместо этогоint | str | float, анализатор типов выдаст ошибку, указывая, чтоunreachableимеет типfloat. Для того чтобы вызовassert_neverпрошёл проверку типов, предполагаемый тип переданного аргумента должен быть базовым типом,Never, и ничем другим.Во время выполнения это вызывает исключение при вызове.
См. также
Unreachable Code and Exhaustiveness Checking содержит дополнительную информацию о проверке полноты с помощью статических типов.
Добавлена в версии 3.11.
-
typing.reveal_type(obj, /) -
Запрос к статическому анализатору типов для вывода предполагаемого типа выражения.
Когда статический анализатор типов сталкивается с вызовом этой функции, он выдает диагностику с предполагаемым типом аргумента. Например:
x: int = 1 reveal_type(x) # Revealed type is "builtins.int"
Это может быть полезно, когда вы хотите отладить, как ваш анализатор типов обрабатывает конкретный фрагмент кода.
Во время выполнения эта функция выводит тип аргумента во время выполнения в
sys.stderrи возвращает аргумент без изменений (позволяя использовать вызов в выражении):x = reveal_type(1) # prints "Runtime type is int" print(x) # prints "1"
Обратите внимание, что тип во время выполнения может отличаться от (более или менее специфичного, чем) статически предполагаемого анализатором типов.
Большинство анализаторов типов поддерживают
reveal_type()в любом месте, даже если имя не импортировано изtyping. Однако импорт имени изtyping, позволяет вашему коду работать без ошибок во время выполнения и более ясно передает намерения.Добавлена в версии 3.11.
-
@typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, field_specifiers=(), **kwargs) -
Декоратор, позволяющий отметить объект как предоставляющий поведение, подобное
dataclass.dataclass_transformможно использовать для декорирования класса, метакласса или функции, которая сама по себе является декоратором. Присутствие@dataclass_transform()сообщает статическому анализатору типов, что декорируемый объект выполняет во время выполнения «магию», преобразующую класс аналогичным образом к@dataclasses.dataclass.Пример использования с функцией-декоратором:
T = TypeVar("T") @dataclass_transform() def create_model(cls: type[T]) -> type[T]: ... return cls @create_model class CustomerModel: id: int name: strДля базового класса:
@dataclass_transform() class ModelBase: ... class CustomerModel(ModelBase): id: int name: strДля метакласса:
@dataclass_transform() class ModelMeta(type): ... class ModelBase(metaclass=ModelMeta): ... class CustomerModel(ModelBase): id: int name: strКлассы
CustomerModel, определенные выше, будут обрабатываться анализаторами типов аналогично классам, созданным с помощью@dataclasses.dataclass. Например, анализаторы типов будут предполагать, что у этих классов есть методы__init__, которые принимаютidиname.Декорируемый класс, метакласс или функция могут принимать следующие аргументы bool, которые анализаторы типов будут предполагать иметь такое же действие, как и на декораторе
@dataclasses.dataclass:init,eq,order,unsafe_hash,frozen,match_args,kw_only, иslots. Значение этих аргументов (TrueилиFalse) должно быть статически вычислимо.Аргументы декоратора
dataclass_transformмогут быть использованы для настройки поведения по умолчанию декорируемого класса, метакласса или функции:- Параметры
-
-
eq_default (bool) – Указывает, предполагается ли параметр
eqравнымTrueилиFalseесли он опущен вызывающей стороной. По умолчаниюTrue. -
order_default (bool) – Указывает, предполагается ли параметр
orderравнымTrueилиFalseесли он опущен вызывающей стороной. По умолчаниюFalse. -
kw_only_default (bool) – Указывает, предполагается ли параметр
kw_onlyравнымTrueилиFalseесли он опущен вызывающей стороной. По умолчаниюFalse. -
field_specifiers (tuple[Callable[..., Any], ...]) – Указывает статический список поддерживаемых классов или функций, описывающих поля, аналогично
dataclasses.field(). По умолчанию(). - **kwargs (Any) – Принимаются произвольные дополнительные ключевые аргументы, чтобы позволить возможные будущие расширения.
-
eq_default (bool) – Указывает, предполагается ли параметр
Анализаторы типов распознают следующие необязательные параметры в спецификаторах полей:
Распознанные параметры для спецификаторов полей Название параметра
Описание
initУказывает, должен ли поле включаться в синтезированный метод
__init__. Если не указано,initпо умолчаниюTrue.defaultПредоставляет значение по умолчанию для поля.
default_factoryПредоставляет обратный вызов во время выполнения, который возвращает значение по умолчанию для поля. Если ни
defaultниdefault_factoryне указаны, поле предполагается без значения по умолчанию и должно получить значение при создании экземпляра класса.factoryПсевдоним для параметра
default_factoryв спецификаторах полей.kw_onlyУказывает, должно ли поле отмечаться как только для ключевых аргументов. Если
True, поле будет только ключевым. ЕслиFalse, оно не будет только ключевым. Если не указано, используется значение параметраkw_onlyна объекте, декорированномdataclass_transform, или если это не указано, используется значениеkw_only_defaultнаdataclass_transform.aliasПредоставляет альтернативное имя для поля. Это альтернативное имя используется в синтезированном методе
__init__.Во время выполнения этот декоратор записывает свои аргументы в атрибут
__dataclass_transform__на декорируемом объекте. Он не имеет других эффектов во время выполнения.См. PEP 681 для получения дополнительной информации.
Добавлена в версии 3.11.
-
@typing.overload -
Декоратор для создания перегруженных функций и методов.
Декоратор
@overloadпозволяет описывать функции и методы, которые поддерживают несколько различных комбинаций типов аргументов. Последовательность определений, помеченных декоратором@overload, должна следовать ровно за одним определением, не помеченным декоратором@overload(для одной и той же функции/метода).Определения, помеченные декоратором
@overload, предназначены только для проверки типов, так как они будут перезаписаны не помеченным декоратором@overloadопределением. Определение, не помеченное декоратором@overload, будет использоваться во время выполнения, но должно игнорироваться проверяющей системой типов. Во время выполнения непосредственное обращение к функции, помеченной декоратором@overload, вызоветNotImplementedError.Пример перегрузки, которая обеспечивает более точный тип, чем можно выразить с помощью объединения или переменной типа:
@overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): ... # actual implementation goes hereСм. PEP 484 для получения более подробной информации и сравнения с другими семантиками типов.
Изменено в версии 3.11: Теперь перегруженные функции могут быть инспектированы во время выполнения с помощью
get_overloads().
-
typing.get_overloads(func) -
Возвращает последовательность определений, помеченных декоратором
@overload, для func.func — это объект функции, реализующий перегруженную функцию. Например, если рассматривать определение
processв документации для@overload,get_overloads(process)вернет последовательность из трех объектов функций для трех определенных перегрузок. Если вызывается для функции без перегрузок,get_overloads()возвращает пустую последовательность.get_overloads()может использоваться для инспектирования перегруженной функции во время выполнения.Введено в версии 3.11.
-
typing.clear_overloads() -
Очищает все зарегистрированные перегрузки в внутренней базе данных.
Это можно использовать для освобождения памяти, используемой базой данных.
Введено в версии 3.11.
-
@typing.final -
Декоратор для указания финальных методов и финальных классов.
Помещение метода декоратором
@finalуказывает проверяющей системе типов, что метод нельзя переопределить в подклассе. Помещение класса декоратором@finalуказывает, что он не может быть подклассом.Например:
class Base: @final def done(self) -> None: ... class Sub(Base): def done(self) -> None: # Error reported by type checker ... @final class Leaf: ... class Other(Leaf): # Error reported by type checker ...Проверки во время выполнения таких свойств нет. См. PEP 591 для получения более подробной информации.
Введено в версии 3.8.
Изменено в версии 3.11: Декоратор теперь попытается установить атрибут
__final__со значениемTrueдля объекта, к которому он применяется. Таким образом, проверка, подобнаяif getattr(obj, "__final__", False), может быть использована во время выполнения для определения, был ли объектobjпомечен как финальный. Если объект, к которому применяется декоратор, не поддерживает установку атрибутов, декоратор возвращает объект без изменений, не вызывая исключение.
-
@typing.no_type_check -
Декоратор, указывающий, что аннотации не являются подсказками типов.
Он работает как декоратор класса или функции. В случае с классом он рекурсивно применяется ко всем методам и классам, определённым в этом классе (но не к методам, определённым в его родительских или дочерних классах). Проверяющие системы типов будут игнорировать все аннотации в функции или классе с этим декоратором.
@no_type_checkизменяет объект, к которому применяется декоратор, непосредственно.
-
@typing.no_type_check_decorator -
Декоратор для предоставления другому декоратору эффекта
no_type_check().Он оборачивает декоратор в нечто, что оборачивает декорированную функцию в
no_type_check().
-
@typing.type_check_only -
Декоратор, помечающий класс или функцию как недоступную во время выполнения.
Этот декоратор сам по себе недоступен во время выполнения. Он в основном предназначен для маркировки классов, определённых в файлах образцов типов, если реализация возвращает экземпляр частного класса:
@type_check_only class Response: # private or not available at runtime code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...Обратите внимание, что возвращение экземпляров частных классов не рекомендуется. Обычно предпочтительнее сделать такие классы общедоступными.
Справочные данные по интроспекции
-
typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False) -
Возвращает словарь, содержащий подсказки типов для функции, метода, модуля или объекта класса.
Это часто то же самое, что
obj.__annotations__. Кроме того, ссылки вперёд, закодированные как строковые литералы, обрабатываются путём их оценки в пространствах имёнglobalsиlocals. Для классаC, возвращается словарь, составленный путём объединения всех__annotations__в порядкеC.__mro__в обратном порядке.Функция рекурсивно заменяет все
Annotated[T, ...]наT, еслиinclude_extrasне установлено вTrue(см.Annotatedдля получения дополнительной информации). Например:class Student(NamedTuple): name: Annotated[str, 'some marker'] assert get_type_hints(Student) == {'name': str} assert get_type_hints(Student, include_extras=False) == {'name': str} assert get_type_hints(Student, include_extras=True) == { 'name': Annotated[str, 'some marker'] }Примечание
get_type_hints()не работает с импортированными псевдонимами типов, которые включают ссылки вперёд. Включение отложенной оценки аннотаций (PEP 563) может устранить необходимость в большинстве ссылок вперёд.Изменено в версии 3.9: Добавлен параметр
include_extrasв рамках PEP 593. Дополнительную информацию см. в документации поAnnotated.Изменено в версии 3.11: Ранее,
Optional[t]добавлялся для аннотаций функций и методов, если значение по умолчанию было равноNone. Теперь аннотация возвращается без изменений.
-
typing.get_origin(tp) -
Получить версию типа без подстановочных значений: для объекта typing вида
X[Y, Z, ...]возвращаетX.Если
X— это псевдоним typing-модуля для встроенного класса или классаcollections, он будет приведён к исходному классу. ЕслиX— экземплярParamSpecArgsилиParamSpecKwargs, возвращается базовыйParamSpec. Для неподдерживаемых объектов возвращаетсяNone.Примеры:
assert get_origin(str) is None assert get_origin(Dict[str, int]) is dict assert get_origin(Union[int, str]) is Union P = ParamSpec('P') assert get_origin(P.args) is P assert get_origin(P.kwargs) is PВведено в версии 3.8.
-
typing.get_args(tp) -
Получить аргументы типа со всеми произведёнными подстановками: для объекта typing вида
X[Y, Z, ...]возвращает(Y, Z, ...).Если
X— это объединение илиLiteral, содержащиеся в другом типе дженериков, порядок(Y, Z, ...)может отличаться от порядка исходных аргументов[Y, Z, ...]из-за кэширования типов. Для неподдерживаемых объектов возвращается().Примеры:
assert get_args(int) == () assert get_args(Dict[int, str]) == (int, str) assert get_args(Union[int, str]) == (int, str)
Введено в версии 3.8.
-
typing.is_typeddict(tp) -
Проверка, является ли тип
TypedDict.Например:
class Film(TypedDict): title: str year: int assert is_typeddict(Film) assert not is_typeddict(list | str) # TypedDict is a factory for creating typed dicts, # not a typed dict itself assert not is_typeddict(TypedDict)Введено в версии 3.10.
-
class typing.ForwardRef -
Класс, используемый для внутреннего представления типов строковых ссылок вперёд.
Например,
List["SomeClass"]неявно преобразуется вList[ForwardRef("SomeClass")].ForwardRefне должен создаваться пользователем, но может использоваться инструментами интроспекции.Примечание
PEP 585 типы дженериков, такие как
list["SomeClass"]не будут неявно преобразованы вlist[ForwardRef("SomeClass")]и, следовательно, не будут автоматически разрешаться вlist[SomeClass].Введено в версии 3.7.4.
Константа
-
typing.TYPE_CHECKING -
Специальная константа, предполагаемая как
Trueсторонними статическими проверяющими типов. ОнаFalseво время выполнения.Использование:
if TYPE_CHECKING: import expensive_mod def fun(arg: 'expensive_mod.SomeType') -> None: local_var: expensive_mod.AnotherType = other_fun()Первая аннотация типа должна быть заключена в кавычки, превращая её в «ссылку вперёд», чтобы скрыть ссылку
expensive_modот интерпретатора во время выполнения. Аннотации типов для локальных переменных не оцениваются, поэтому вторая аннотация не нуждается в кавычках.Примечание
Если используется
from __future__ import annotations, аннотации не оцениваются во время определения функции. Вместо этого они хранятся как строки в__annotations__. Это делает ненужным использование кавычек вокруг аннотации (см. PEP 563).Введено в версии 3.5.2.
Устаревшие псевдонимы
Этот модуль определяет несколько устаревших псевдонимов для существующих классов стандартной библиотеки. Изначально они были включены в модуль typing для поддержки параметризации этих обобщенных классов с помощью []. Однако псевдонимы стали избыточными в Python 3.9, когда соответствующие существующие классы были расширены для поддержки [] (см. PEP 585).
Избыточные типы устарели начиная с Python 3.9. Однако, хотя псевдонимы могут быть удалены в какой-то момент, удаление этих псевдонимов в настоящее время не планируется. Поэтому интерпретатор в настоящее время не выдает предупреждений об устаревании для этих псевдонимов.
Если в какой-то момент будет принято решение об удалении этих устаревших псевдонимов, интерпретатор будет выдавать предупреждение об устаревании как минимум за два выпуска до удаления. Псевдонимы гарантированно останутся в модуле typing без предупреждений об устаревании как минимум до Python 3.14.
Проверяющие типы рекомендуют отмечать использование устаревших типов, если программа, которую они проверяют, ориентирована на минимальную версию Python 3.9 или более новую.
Псевдонимы встроенных типов
-
class typing.Dict(dict, MutableMapping[KT, VT]) -
Устаревший псевдоним для
dict.Обратите внимание, что для аннотации аргументов предпочтительнее использовать абстрактный тип коллекции, такой как
Mapping, а неdictилиtyping.Dict.Этот тип можно использовать следующим образом:
def count_words(text: str) -> Dict[str, int]: ...Устарел начиная с версии 3.9:
builtins.dictтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.List(list, MutableSequence[T]) -
Устаревший псевдоним для
list.Обратите внимание, что для аннотации аргументов предпочтительнее использовать абстрактный тип коллекции, такой как
SequenceилиIterable, а неlistилиtyping.List.Этот тип можно использовать следующим образом:
T = TypeVar('T', int, float) def vec2(x: T, y: T) -> List[T]: return [x, y] def keep_positives(vector: Sequence[T]) -> List[T]: return [item for item in vector if item > 0]Устарел начиная с версии 3.9:
builtins.listтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.Set(set, MutableSet[T]) -
Устаревший псевдоним для
builtins.set.Обратите внимание, что для аннотации аргументов предпочтительнее использовать абстрактный тип коллекции, такой как
AbstractSet, а неsetилиtyping.Set.Устарел начиная с версии 3.9:
builtins.setтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.FrozenSet(frozenset, AbstractSet[T_co]) -
Устаревший псевдоним для
builtins.frozenset.Устарел начиная с версии 3.9:
builtins.frozensetтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
typing.Tuple -
Устаревший псевдоним для
tuple.tupleиTupleявляются специальными случаями в системе типов; см. Аннотирование кортежей для получения дополнительных сведений.Устарел начиная с версии 3.9:
builtins.tupleтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.Type(Generic[CT_co]) -
Устаревший псевдоним для
type.См. Тип объектов класса для получения подробной информации об использовании
typeилиtyping.Typeв аннотациях типов.Добавлен в версии 3.5.2.
Устарел начиная с версии 3.9:
builtins.typeтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
Псевдонимы типов в collections
-
class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT]) -
Устаревший псевдоним для
collections.defaultdict.Новая версия 3.5.2.
Устарело с версии 3.9:
collections.defaultdictтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.
-
class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT]) -
Устаревший псевдоним для
collections.OrderedDict.Новая версия 3.7.2.
Устарело с версии 3.9:
collections.OrderedDictтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.
-
class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT]) -
Устаревший псевдоним для
collections.ChainMap.Новая версия 3.5.4.
Новая версия 3.6.1.
Устарело с версии 3.9:
collections.ChainMapтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.
-
class typing.Counter(collections.Counter, Dict[T, int]) -
Устаревший псевдоним для
collections.Counter.Новая версия 3.5.4.
Новая версия 3.6.1.
Устарело с версии 3.9:
collections.Counterтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.
-
class typing.Deque(deque, MutableSequence[T]) -
Устаревший псевдоним для
collections.deque.Новая версия 3.5.4.
Новая версия 3.6.1.
Устарело с версии 3.9:
collections.dequeтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщённого псевдонима.
Псевдонимы других конкретных типов
-
class typing.Pattern -
class typing.Match -
Устаревшие псевдонимы, соответствующие типам возвращаемых значений
re.compile()иre.match().Эти типы (и соответствующие функции) являются обобщёнными относительно
AnyStr.Patternможет быть специализирован какPattern[str]илиPattern[bytes];Matchможет быть специализирован какMatch[str]илиMatch[bytes].Устарело с версии 3.8, будет удалено в версии 3.13: Пространство имён
typing.reустарело и будет удалено. Эти типы следует импортировать напрямую изtyping.Устарело с версии 3.9: Классы
PatternиMatchизreтеперь поддерживают[]. См. PEP 585 и Тип обобщённого псевдонима.
-
class typing.Text -
Устаревший псевдоним для
str.Textпредоставлен для обеспечения обратной совместимости кода Python 2: в Python 2Textявляется псевдонимом дляunicode.Используйте
Textдля указания, что значение должно содержать строку Unicode, совместимую как с Python 2, так и с Python 3:def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'Новая версия 3.5.2.
Устарело с версии 3.11: Python 2 больше не поддерживается, и большинство проверяющих типов больше не поддерживают проверку типов кода Python 2. Удаление псевдонима в настоящее время не планируется, но пользователям рекомендуется использовать
strвместоText.
Псевдонимы контейнерных ABC в collections.abc
-
class typing.AbstractSet(Collection[T_co]) -
Устаревший псевдоним для
collections.abc.Set.Устарело начиная с версии 3.9:
collections.abc.Setтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.ByteString(Sequence[int]) -
Этот тип представляет типы
bytes,bytearrayиmemoryviewпоследовательностей байтов.Устарело начиная с версии 3.9, будет удалено в версии 3.14: Предпочтительнее
typing_extensions.Buffer, или объединение, такое какbytes | bytearray | memoryview.
-
class typing.Collection(Sized, Iterable[T_co], Container[T_co]) -
Устаревший псевдоним для
collections.abc.Collection.Введено в версии 3.6.0.
Устарело начиная с версии 3.9:
collections.abc.Collectionтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.Container(Generic[T_co]) -
Устаревший псевдоним для
collections.abc.Container.Устарело начиная с версии 3.9:
collections.abc.Containerтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]]) -
Устаревший псевдоним для
collections.abc.ItemsView.Устарело начиная с версии 3.9:
collections.abc.ItemsViewтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.KeysView(MappingView, AbstractSet[KT_co]) -
Устаревший псевдоним для
collections.abc.KeysView.Устарело начиная с версии 3.9:
collections.abc.KeysViewтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.Mapping(Collection[KT], Generic[KT, VT_co]) -
Устаревший псевдоним для
collections.abc.Mapping.Этот тип можно использовать следующим образом:
def get_position_in_index(word_list: Mapping[str, int], word: str) -> int: return word_list[word]Устарело начиная с версии 3.9:
collections.abc.Mappingтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.MappingView(Sized) -
Устаревший псевдоним для
collections.abc.MappingView.Устарело начиная с версии 3.9:
collections.abc.MappingViewтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.MutableMapping(Mapping[KT, VT]) -
Устаревший псевдоним для
collections.abc.MutableMapping.Устарело начиная с версии 3.9:
collections.abc.MutableMappingтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.MutableSequence(Sequence[T]) -
Устаревший псевдоним для
collections.abc.MutableSequence.Устарело начиная с версии 3.9:
collections.abc.MutableSequenceтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.MutableSet(AbstractSet[T]) -
Устаревший псевдоним для
collections.abc.MutableSet.Устарело начиная с версии 3.9:
collections.abc.MutableSetтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.Sequence(Reversible[T_co], Collection[T_co]) -
Устаревший псевдоним для
collections.abc.Sequence.Устарело начиная с версии 3.9:
collections.abc.Sequenceтеперь поддерживает индексацию ([]). См. PEP 585 и Тип псевдонима дженерика.
-
class typing.ValuesView(MappingView, Collection[_VT_co]) -
Устаревшее псевдоним к
collections.abc.ValuesView.Устарело начиная с версии 3.9:
collections.abc.ValuesViewтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
Псевдонимы асинхронных ABC в collections.abc
-
class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType]) -
Устаревшее псевдоним к
collections.abc.Coroutine.Изменение типов и порядок переменных соответствуют
Generator, например:from collections.abc import Coroutine c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: y = await c # Inferred type of 'y' is intДобавлено в версии 3.5.3.
Устарело начиная с версии 3.9:
collections.abc.Coroutineтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType]) -
Устаревшее псевдоним к
collections.abc.AsyncGenerator.Асинхронный генератор может быть аннотирован обобщенным типом
AsyncGenerator[YieldType, SendType]. Например:async def echo_round() -> AsyncGenerator[int, float]: sent = yield 0 while sent >= 0.0: rounded = await round(sent) sent = yield roundedВ отличие от обычных генераторов, асинхронные генераторы не могут возвращать значение, поэтому нет параметра типа
ReturnType. Как и вGenerator, параметрSendTypeизменяется контравариантно.Если ваш генератор будет только генерировать значения, задайте параметр
SendTypeвNone:async def infinite_stream(start: int) -> AsyncGenerator[int, None]: while True: yield start start = await increment(start)В качестве альтернативы, аннотируйте ваш генератор как имеющий тип возвращаемого значения
AsyncIterable[YieldType]илиAsyncIterator[YieldType]:async def infinite_stream(start: int) -> AsyncIterator[int]: while True: yield start start = await increment(start)Добавлено в версии 3.6.1.
Устарело начиная с версии 3.9:
collections.abc.AsyncGeneratorтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.AsyncIterable(Generic[T_co]) -
Устаревшее псевдоним к
collections.abc.AsyncIterable.Добавлено в версии 3.5.2.
Устарело начиная с версии 3.9:
collections.abc.AsyncIterableтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.AsyncIterator(AsyncIterable[T_co]) -
Устаревшее псевдоним к
collections.abc.AsyncIterator.Добавлено в версии 3.5.2.
Устарело начиная с версии 3.9:
collections.abc.AsyncIteratorтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
-
class typing.Awaitable(Generic[T_co]) -
Устаревшее псевдоним к
collections.abc.Awaitable.Добавлено в версии 3.5.2.
Устарело начиная с версии 3.9:
collections.abc.Awaitableтеперь поддерживает индексирование ([]). См. PEP 585 и Тип обобщенного псевдонима.
Псевдонимы для других ABC в collections.abc
-
class typing.Iterable(Generic[T_co]) -
Устаревший псевдоним для
collections.abc.Iterable.Устарело начиная с версии 3.9:
collections.abc.Iterableтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.
-
class typing.Iterator(Iterable[T_co]) -
Устаревший псевдоним для
collections.abc.Iterator.Устарело начиная с версии 3.9:
collections.abc.Iteratorтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.
-
typing.Callable -
Устаревший псевдоним для
collections.abc.Callable.См. Аннотирование вызываемых объектов для подробностей о том, как использовать
collections.abc.Callableиtyping.Callableв аннотациях типов.Устарело начиная с версии 3.9:
collections.abc.Callableтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.Изменено в версии 3.10:
Callableтеперь поддерживаетParamSpecиConcatenate. См. PEP 612 для получения дополнительной информации.
-
class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType]) -
Устаревший псевдоним для
collections.abc.Generator.Генератор может быть аннотирован обобщенным типом
Generator[YieldType, SendType, ReturnType]. Например:def echo_round() -> Generator[int, float, str]: sent = yield 0 while sent >= 0: sent = yield round(sent) return 'Done'Обратите внимание, что в отличие от многих других обобщений в модуле typing, поведение
SendTypeGeneratorявляется контравариантным, а не ковариантным или инвариантным.Если ваш генератор будет выдавать только значения, установите
SendTypeиReturnTypeнаNone:def infinite_stream(start: int) -> Generator[int, None, None]: while True: yield start start += 1В качестве альтернативы, аннотируйте свой генератор как имеющий возвращаемый тип
Iterable[YieldType]илиIterator[YieldType]:def infinite_stream(start: int) -> Iterator[int]: while True: yield start start += 1Устарело начиная с версии 3.9:
collections.abc.Generatorтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.
-
class typing.Hashable -
Псевдоним для
collections.abc.Hashable.
-
class typing.Reversible(Iterable[T_co]) -
Устаревший псевдоним для
collections.abc.Reversible.Устарело начиная с версии 3.9:
collections.abc.Reversibleтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.
-
class typing.Sized -
Псевдоним для
collections.abc.Sized.
Псевдонимы для contextlib ABC
-
class typing.ContextManager(Generic[T_co]) -
Устаревший псевдоним для
contextlib.AbstractContextManager.Добавлена в версии 3.5.4.
Добавлена в версии 3.6.0.
Устарело начиная с версии 3.9:
contextlib.AbstractContextManagerтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.
-
class typing.AsyncContextManager(Generic[T_co]) -
Устаревший псевдоним для
contextlib.AbstractAsyncContextManager.Добавлена в версии 3.5.4.
Добавлена в версии 3.6.2.
Устарело начиная с версии 3.9:
contextlib.AbstractAsyncContextManagerтеперь поддерживает индексирование ([]). См. PEP 585 и Тип Обобщенного Псевдонима.
График устаревания основных функций
Определенные функции в typing устарели и могут быть удалены в будущей версии Python. В следующей таблице обобщены основные устаревания для удобства. Это может быть изменено, и не все устаревания указаны.
Функция | Устарела в | Прогнозируемое удаление | PEP/вопрос |
|---|---|---|---|
| 3.8 | 3.13 | |
| 3.9 | Не определено (см. Устаревшие псевдонимы для получения дополнительной информации) | |
3.9 | 3.14 | ||
3.11 | Не определено |
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/typing.html