Не используется в аннотациях, являются строительным блоком для объявления типов.
from typing import TypedDict # Новое в Python 3.8. TypedDict(dict)
dict
- словарь.Тип аннотации TypedDict()
модуля typing
представляет собой специальную конструкцию для добавления аннотаций типов в словарь. Во время выполнения это простой словарь dict
.
TypedDict
объявляет тип словаря, который ожидает, что все его экземпляры будут иметь определенный набор ключей, где каждый ключ связан со значением согласованного типа. Это ожидание не проверяется во время выполнения, а выполняется только средствами проверки типизации.
Применение:
from typing import TypedDict class Point2D(TypedDict): x: int y: int label: str # Проверка проходит a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # Не удается проверить тип b: Point2D = {'z': 3, 'label': 'bad'} assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
Информация о типе для интроспекции может быть доступна через Point2D.__ annotations__
и Point2D.__total__
.
Чтобы разрешить использование этой функции со старыми версиями Python, тип аннотации TypedDict
поддерживает две дополнительные эквивалентные синтаксические формы:
# Использование буквального словаря в качестве второго аргумента: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) # Использование ключевых аргументов: Point2D = TypedDict('Point2D', x=int, y=int, label=str)
Синтаксис ключевых аргументов устарел начиная с Python 3.11, будет удален в Python 3.13. Он также может не поддерживаться средствами проверки статических типов.
Функциональный синтаксис также следует использовать, когда какой-либо из ключей не является допустимым идентификатором, например, потому что он является ключевым словом или содержит дефис. Пример:
from typing import TypedDict # вызывает синтаксическую ошибку class Point2D(TypedDict): in: int # 'in' - это ключевое слово x-y: int # имя с дефисами # OK Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
По умолчанию все ключи должны присутствовать в TypedDict
. Отдельные ключи можно пометить как необязательные с помощью typing.NotRequired
:
from typing import TypedDict, NotRequired class Point2D(TypedDict): x: int y: int label: NotRequired[str] # Альтернативный синтаксис Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})
Это означает, что в Point2D()
в TypedDict
ключ label
может быть опущен.
Также можно пометить все ключи как необязательные по умолчанию, указав в совокупности значение False
:
from typing import TypedDict class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)
Это означает, что в Point2D
, TypedDict
любой из ключей может быть опущен. Ожидается, что средство проверки типов будет поддерживать только литерал False
или True
в качестве значения общего аргумента. True
- это значение по умолчанию, которое делает обязательными все элементы, определенные в теле класса.
Отдельные ключи total=False
в TypedDict
могут быть помечены как требуемые с помощью typing.Required
:
from typing import TypedDict, Required class Point2D(TypedDict, total=False): x: Required[int] y: Required[int] label: str # Альтернативный синтаксис Point2D = TypedDict('Point2D', { 'x': Required[int], 'y': Required[int], 'label': str }, total=False)
Тип typing.TypedDict
может наследовать от одного или нескольких других типов TypedDict
, используя синтаксис на основе классов.
Применение:
class Point3D(Point2D): z: int
Класс Point3D
имеет три элемента: x
, y
и z
. Это эквивалентно этому определению:
from typing import TypedDict class Point3D(TypedDict): x: int y: int z: int
typing.TypedDict
не может наследовать от класса, отличного от TypedDict
, за исключением typing.Generic
. Например:
from typing import TypedDict, Generic, TypeVar class X(TypedDict): x: int class Y(TypedDict): y: int # Класс без TypedDict class Z(object): pass # Проходит проверку class XY(X, Y): pass # вызывает ошибку типа class XZ(X, Z): pass T = TypeVar('T') # вызывает TypeError class XT(X, Generic[T]): pass
TypedDict
может быть общим:
from typing import TypedDict, Generic class Group(TypedDict, Generic[T]): key: T group: list[T]
typing.TypedDict
может быть универсальным:
class Group[T](TypedDict): key: T group: list[T]
Чтобы создать универсальный TypedDict
, совместимый с Python 3.11 или более ранней версии, явно наследуйте от Generic
:
T = TypeVar("T") class Group(TypedDict, Generic[T]): key: T group: list[T]
typing.TypedDict
можно проанализировать с помощью словарных аннотаций, __total__
, __required_keys__
и __optional_keys__
.__total__
:Point2D.__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
Этот атрибут отражает только значение общего аргумента текущего класса TypedDict
, а не то, является ли класс семантически полным. Например, TypedDict
с __total__
, установленным в True
, может иметь ключи, отмеченные NotRequired
, или он может наследовать от другого TypedDict
с total=False
. Поэтому для самоанализа обычно лучше использовать __required_keys__
и __optional_keys__
.
__required_keys__
:__optional_keys__
:Новое в Python 3.9.
Point2D.__required_keys__
и Point2D.__optional_keys__
возвращают frozenset
объекты, содержащие обязательные и необязательные ключи соответственно.
Ключи, помеченные как "обязательные", всегда будут отображаться в __required_keys__
, а ключи, отмеченные как "необязательные", всегда будут отображаться в __optional_keys__
.
Для обратной совместимости с Python 3.10 и ниже также можно использовать наследование для объявления как обязательных, так и необязательных ключей в одном и том же TypedDict
. Это делается путем объявления TypedDict
с одним значением для итогового аргумента и последующего наследования от него другого TypedDict
с другим значением для итогового значения:
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
Примечание. Если используются аннотации импорта
from __future__
или аннотации задаются в виде строк, то аннотации не оцениваются при определенииTypedDict
. Таким образом, самоанализ во время выполнения, на который полагаются__required_keys__
и__optional_keys__
, может работать неправильно, а значения атрибутов могут быть неправильными.
Изменено в Python 3.11: добавлена поддержка пометки отдельных ключей как
Required
илиNotRequired
.Изменено в Python 3.11: Добавлена поддержка общих
TypedDict
.