@@ -1056,26 +1056,120 @@ These are not used in annotations. They are building blocks for declaring types.
1056
1056
1057
1057
assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
1058
1058
1059
- The type info for introspection can be accessed via ``Point2D.__annotations__ ``
1060
- and ``Point2D.__total__ ``. To allow using this feature with older versions
1061
- of Python that do not support :pep: `526 `, ``TypedDict `` supports two additional
1062
- equivalent syntactic forms::
1059
+ To allow using this feature with older versions of Python that do not
1060
+ support :pep: `526 `, ``TypedDict `` supports two additional equivalent
1061
+ syntactic forms:
1062
+
1063
+ * Using a literal :class: `dict ` as the second argument::
1063
1064
1064
- Point2D = TypedDict('Point2D', x=int, y=int, label=str)
1065
1065
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
1066
1066
1067
- By default, all keys must be present in a TypedDict. It is possible
1068
- to override this by specifying totality.
1067
+ * Using keyword arguments::
1068
+
1069
+ Point2D = TypedDict('Point2D', x=int, y=int, label=str)
1070
+
1071
+ The functional syntax should also be used when any of the keys are not valid
1072
+ :ref: `identifiers `, for example because they are keywords or contain hyphens.
1073
+ Example::
1074
+
1075
+ # raises SyntaxError
1076
+ class Point2D(TypedDict):
1077
+ in: int # 'in' is a keyword
1078
+ x-y: int # name with hyphens
1079
+
1080
+ # OK, functional syntax
1081
+ Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
1082
+
1083
+ By default, all keys must be present in a ``TypedDict ``. It is possible to
1084
+ override this by specifying totality.
1069
1085
Usage::
1070
1086
1071
- class point2D (TypedDict, total=False):
1087
+ class Point2D (TypedDict, total=False):
1072
1088
x: int
1073
1089
y: int
1074
1090
1075
- This means that a point2D TypedDict can have any of the keys omitted. A type
1076
- checker is only expected to support a literal False or True as the value of
1077
- the total argument. True is the default, and makes all items defined in the
1078
- class body be required.
1091
+ # Alternative syntax
1092
+ Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)
1093
+
1094
+ This means that a ``Point2D `` ``TypedDict `` can have any of the keys
1095
+ omitted. A type checker is only expected to support a literal ``False `` or
1096
+ ``True `` as the value of the ``total `` argument. ``True `` is the default,
1097
+ and makes all items defined in the class body required.
1098
+
1099
+ It is possible for a ``TypedDict `` type to inherit from one or more other ``TypedDict `` types
1100
+ using the class-based syntax.
1101
+ Usage::
1102
+
1103
+ class Point3D(Point2D):
1104
+ z: int
1105
+
1106
+ ``Point3D `` has three items: ``x ``, ``y `` and ``z ``. It is equivalent to this
1107
+ definition::
1108
+
1109
+ class Point3D(TypedDict):
1110
+ x: int
1111
+ y: int
1112
+ z: int
1113
+
1114
+ A ``TypedDict `` cannot inherit from a non-TypedDict class,
1115
+ notably including :class: `Generic `. For example::
1116
+
1117
+ class X(TypedDict):
1118
+ x: int
1119
+
1120
+ class Y(TypedDict):
1121
+ y: int
1122
+
1123
+ class Z(object): pass # A non-TypedDict class
1124
+
1125
+ class XY(X, Y): pass # OK
1126
+
1127
+ class XZ(X, Z): pass # raises TypeError
1128
+
1129
+ T = TypeVar('T')
1130
+ class XT(X, Generic[T]): pass # raises TypeError
1131
+
1132
+ A ``TypedDict `` can be introspected via :attr: `__annotations__ `,
1133
+ :attr: `__total__ `, :attr: `__required_keys__ `, and :attr: `__optional_keys__ `.
1134
+
1135
+ .. attribute :: __total__
1136
+
1137
+ ``Point2D.__total__ `` gives the value of the ``total `` argument.
1138
+ Example::
1139
+
1140
+ >>> from typing import TypedDict
1141
+ >>> class Point2D(TypedDict): pass
1142
+ >>> Point2D.__total__
1143
+ True
1144
+ >>> class Point2D(TypedDict, total=False): pass
1145
+ >>> Point2D.__total__
1146
+ False
1147
+ >>> class Point3D(Point2D): pass
1148
+ >>> Point3D.__total__
1149
+ True
1150
+
1151
+ .. attribute :: __required_keys__
1152
+ .. attribute :: __optional_keys__
1153
+
1154
+ ``Point2D.__required_keys__ `` and ``Point2D.__optional_keys__ `` return
1155
+ :class: `frozenset ` objects containing required and non-required keys, respectively.
1156
+ Currently the only way to declare both required and non-required keys in the
1157
+ same ``TypedDict `` is mixed inheritance, declaring a ``TypedDict `` with one value
1158
+ for the ``total `` argument and then inheriting it from another ``TypedDict `` with
1159
+ a different value for ``total ``.
1160
+ Usage::
1161
+
1162
+ >>> class Point2D(TypedDict, total=False):
1163
+ ... x: int
1164
+ ... y: int
1165
+ ...
1166
+ >>> class Point3D(Point2D):
1167
+ ... z: int
1168
+ ...
1169
+ >>> Point3D.__required_keys__ == frozenset({'z'})
1170
+ True
1171
+ >>> Point3D.__optional_keys__ == frozenset({'x', 'y'})
1172
+ True
1079
1173
1080
1174
See :pep: `589 ` for more examples and detailed rules of using ``TypedDict ``.
1081
1175
0 commit comments