В разделе представлены функции и декораторы модуля typing
, представляющие дополнительные возможности по аннотированию исходного кода.
typing
:typing.cast()
приводит значение к типу,typing.assert_type()
просит средство проверки подтвердить тип,typing.assert_never()
просит средство проверки подтвердить, что строка кода недоступна,typing.reveal_type()
выявляет предполагаемый статический тип выражения,typing
:@typing.dataclass_transform()
используется для декорирования класса, метакласса или функции, которая сама является декоратором,@typing.overload
описывает функции с комбинациями типов аргументов,@typing.get_overloads()
возвращает последовательность определений @typing.overload
,@typing.clear_overloads
очищает все зарегистрированные перегрузки,@typing.final
метод не может быть переопределен,@typing.no_type_check
указывает, что аннотации не являются подсказками типа,@typing.no_type_check_decorator
дает другому декоратору эффект @typing.no_type_check
@typing.override
указывает, что метод в подклассе предназначен для переопределения метода или атрибута в суперклассе, @typing.type_check_only
помечает класс или функцию как недоступные во время выполнения.typing
.typing.cast(typ, val)
:Функция typing.cast()
приводит значение val
к типу typ
.
Функция возвращает значение без изменений. Для средства проверки типов это означает, что возвращаемое значение имеет обозначенный тип, но во время выполнения намеренно ничего не проверяется, чтобы старт программы был как можно быстрее.
typing.assert_type(val, typ, /)
:Новое в Python 3.11.
Функция typing.assert_type()
(добавлена в Python 3.11.) просит средство проверки статического типа подтвердить, что val
имеет предполагаемый тип typ
.
Когда средство проверки типов встречает вызов typing.assert_type()
, оно выдает ошибку, если значение не относится к указанному типу:
def greet(name: str) -> None: # ОК, предположительный тип `name` - `str` assert_type(name, str) # ошибка проверки типа assert_type(name, int)
Во время выполнения программы этот вызов возвращает первый аргумент без изменений и без побочных эффектов.
Эта функция полезна для того, чтобы гарантировать, что понимание скрипта программой проверки типов соответствует намерениям разработчика:
def complex_function(arg: object): # Допустим здесь выполняется некоторая сложная логика по сужению # типа, в результате чего итоговый тип должен быть `int` ... # здесь проверяется, правильно ли средство # проверки типов понимает написанную функцию assert_type(arg, int)
typing.assert_never(arg, /)
:Новое в Python 3.11.
Функция typing.assert_never()
(добавлена в Python 3.11.) просит средство проверки статического типа подтвердить, что строка кода недоступна.
Пример:
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)
Здесь аннотации позволяют средству проверки типов сделать вывод, что последний случай в case
никогда не может быть выполнен, потому что arg
- это либо целое число, либо строка, и оба варианта охватываются более ранними случаями. Если средство проверки типов обнаружит, что вызов typing.assert_never()
достижим, то он выдаст ошибку. Например, если аннотация типа для arg
была вместо int | str | float
, то средство проверки типов выдаст ошибку, указывающую, что unreachable
имеет тип float
. Чтобы вызов assert_never()
прошел проверку типа, предполагаемый тип передаваемого аргумента должен быть нижним типом typing.Never
и никаким другим.
Во время выполнения программы, если произошел вызов функции typing.assert_never()
, поднимается исключение.
typing.reveal_type(obj, /)
:Новое в Python 3.11.
Функция typing.reveal_type()
(добавлена в Python 3.11.) выявляет предполагаемый статический тип выражения.
Когда средство проверки статического типа встречает вызов этой функции, она выдает диагностику с типом аргумента. Например:
x: int = 1 reveal_type(x) # Выявленный тип - 'builtins.int'
Это может быть полезно, когда нужно отладить, как программа проверки типов обрабатывает определенный фрагмент кода.
Функция возвращает свой аргумент без изменений, что позволяет использовать его в выражении:
x = reveal_type(1) # Выявленный тип - 'builtins.int'
Большинство средств проверки типов поддерживают функцию manifest_type()
в любом месте, даже если имя не импортируется из набора текста. Импорт имени из набора позволяет коду работать без ошибок во время выполнения и более четко передает намерение.
Во время выполнения программы эта функция печатает тип времени выполнения своего аргумента в stderr
и возвращает его без изменений:
x = reveal_type(1) # в `stderr` выводит "Runtime type is int" print(x) # печатает "1"
typing
.@typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)
:Новое в Python 3.11.
Декоратор @typing.dataclass_transform
(добавлен в Python 3.11) позволяющий пометить объект как обеспечивающий поведение, подобное классу данных.
@typing.dataclass_transform
может использоваться для украшения класса, метакласса или функции, которая сама является декоратором. Наличие @dataclass_transform()
сообщает средству проверки статического типа, что декорированный объект выполняет "магию" во время выполнения, которая преобразует класс, придавая ему поведение, подобное @dataclasses.dataclass()
.
Аргументы декоратора @dataclass_transform()
можно использовать для настройки поведения декорированного класса, метакласса или функции по умолчанию:
eq_default
: указывает, считается ли параметр eq
равным True
или False
, если он опущен вызывающей стороной.order_default
: указывает, считается ли параметр order
равным True
или False
, если он опущен вызывающей стороной.kw_only_default
указывает, считается ли параметр kw_only
равным True
или False
, если он опущен вызывающей стороной.frozen_default
(добавлен в Python 3.12) указывает, считается ли параметр frozen
равным True
или False
, если он опущен вызывающей стороной. По умолчанию установлено значение False
.field_specifiers
указывает статический список поддерживаемых классов или функций, описывающих поля, аналогично dataclasses.field()
.**kwargs
(Any
) произвольные аргументы других ключевых слов, чтобы обеспечить возможность возможных расширений в будущем.
Распознанные параметры для спецификаторов полей:
init
: указывает, должно ли поле быть включено в синтезированный метод __init__
. Если не указано, то init
по умолчанию имеет значение True
.default
: предоставляет значение по умолчанию для поля.default_factory
: обеспечивает обратный вызов во время выполнения, который возвращает значение по умолчанию для поля. Если ни default
, ни default_factory
не указаны, то предполагается, что поле не имеет значения по умолчанию и должно быть предоставлено значение при создании экземпляра класса.factory
: - это псевдоним для default_factory
.kw_only
: указывает, должно ли поле быть помечено только как ключевое слово. Если True
, то поле будет содержать только ключевые слова. Если False
, то это не будет только ключевое слово. Если не указано, то будет использоваться значение параметра kw_only
для объекта, декорированного с помощью dataclass_transform
, или, если он не указан, то будет использоваться значение kw_only_default
для dataclass_transform
.alias
: предоставляет альтернативное имя для поля. Это альтернативное имя используется в синтезированном методе __init__
.Во время выполнения этот декоратор записывает свои аргументы в атрибут __dataclass_transform__
оформленного объекта и не имеет никакого другого эффекта.
Пример использования:
import typing # !!! определим `T`, если версии Python <= 3.11 T = typing.TypeVar("T") # определяется декоратор `@create_model()`. @typing.dataclass_transform() def create_model(cls: type[T]) -> type[T]: cls.__init__ = ... cls.__eq__ = ... cls.__ne__ = ... return cls # Теперь можно использовать декоратор `@create_model` # для создания новых классов моделей: @create_model class CustomerModel: id: int name: str c = CustomerModel(id=327, name="Eric Idle")
Пример использования в базовом классе:
@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__()
, которые принимают идентификатор и имя.
Декорированный класс, метакласс или функция могут принимать следующие логические аргументы, которые, как предполагают средства проверки типов, имеют тот же эффект, что и декоратор @dataclasses.dataclass
: init
, eq
, order
, unsafe_hash
, frozen
, match_args
, kw_only
и slots
. Должна быть возможность статической оценки значений этих аргументов (True
или False
).
@typing.overload
:Декоратор @typing.overload()
позволяет описывать функции и методы, которые поддерживают несколько различных комбинаций типов аргументов. За серией определений с @overload
должно следовать ровно одно определение без @overload
(для той же функции/метода).
Определения, декорированные @overload
, предназначены только для проверки типов, так как они будут перезаписаны определением без @overload
, в то время как последнее используется во время выполнения, но должно игнорироваться средством проверки типов. Во время выполнения прямой вызов функции с @overload
вызовет исключение NotImplementedError
. Пример перегрузки, которая дает более точный тип, чем можно выразить с помощью typing.Union
или типов переменной:
@overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): <фактическая реализация>
Изменено в Python 3.11: теперь перегруженные функции можно анализировать во время выполнения с помощью
@typing.get_overloads()
.
@typing.get_overloads(func)
:Новое в Python 3.11.
Декоратор @typing.get_overloads()
(добавлен в Python 3.11) возвращает последовательность определений @typing.overload
- оформленные определения для функции func
. Аргумент func
- это объект функции для реализации перегруженной функции. Например, учитывая определение процесса в документации для @overload
, @get_overloads(process)
вернет последовательность из трех функциональных объектов для трех определенных перегрузок. При вызове функции без перегрузок @get_overloads()
возвращает пустую последовательность.
Декоратор @typing.get_overloads()
можно использовать для самоанализа перегруженной функции во время выполнения программы.
@typing.clear_overloads
:Новое в Python 3.11.
Декоратор @typing.clear_overloads()
(добавлен в Python 3.11) очищает все зарегистрированные перегрузки во внутреннем реестре. Такое поведение можно использовать для освобождения памяти, используемой реестром.
@typing.final
:Новое в Python 3.8.
Декоратор @typing.final()
указывает средствам проверки типов, что декорированный метод не может быть переопределен, а декорированный класс не может быть подклассом.
Например:
class Base: @final def done(self) -> None: ... class Sub(Base): def done(self) -> None: # Error reported by type checker ... @final class Leaf: ... class Other(Leaf): # Error reported by type checker ...
Проверка этих свойств во время выполнения отсутствует.
Изменено в Python 3.11: теперь декоратор устанавливает атрибут
__final__
в значениеTrue
декорированного объекта. Таким образом, проверка вродеif getattr(obj, '__final__', False):
может использоваться во время выполнения, чтобы определить, был ли объектobj
помечен как окончательный. Если декорированный объект не поддерживает настройку атрибутов, то декоратор возвращает объект без изменений, не вызывая исключения.
@typing.no_type_check
:Декоратор @typing.no_type_check()
указывает, что аннотации не являются подсказками типа.
Он работает как декоратор класса или функции. С классом, он рекурсивно применяется ко всем методам, определенным в этом классе.
Обратите внимание, что декоратор НЕ применяется к методам, определенным в его суперклассах или подклассах.
Декоратор @typing.no_type_check()
изменяет функции на месте.
@typing.no_type_check_decorator
:Декоратор @typing.no_type_check_decorator()
дает другому декоратору эффект @typing.no_type_check()
.
@typing.override
:Новое в Python 3.12.
Декоратор @typing.override
указывает, что метод в подклассе предназначен для переопределения метода или атрибута в суперклассе.
Средства проверки типов должны выдавать ошибку, если метод, украшенный @override
, фактически ничего не переопределяет. Это помогает предотвратить ошибки, которые могут возникнуть при изменении базового класса без эквивалентного изменения дочернего класса.
Например:
from typing import override class Base: def get_color(self) -> str: return "blue" class GoodChild(Base): # ок: класс переопределяет Base.get_color @override def get_color(self) -> str: return "yellow" class BadChild(Base): # ошибка проверки типа: класс не переопределяет Base.get_color @override def get_colour(self) -> str: return "red"
Проверка во время выполнения не выполняется.
Декоратор попытается установить для атрибута __override__
значение True
на декорируемом объекте. Таким образом, проверку типа getattr(obj, '__override__', False)
можно использовать во время выполнения, чтобы определить, был ли объект obj
помечен как переопределяющий. Если декорированный объект не поддерживает установку атрибутов, то декоратор возвращает объект без изменений, не вызывая исключения.
@typing.type_check_only
:Декоратор @typing.type_check_only()
помечает класс или функцию как недоступные во время выполнения.
Этот декоратор сам по себе недоступен во время выполнения. В основном он предназначен для маркировки классов, определенных в файлах-заглушках типов, если реализация возвращает экземпляр частного класса:
@type_check_only class Response: # частный или недоступный во время выполнения code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...
Обратите внимание, что возвращать экземпляры закрытых классов не рекомендуется. Обычно предпочтительнее делать такие классы публичными.