| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1469,9 +1469,6 @@ These are not used in annotations. They are building blocks for declaring types. | |||
| 1469 | 1469 | ||
| 1470 | 1470 | assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') | |
| 1471 | 1471 | ||
| 1472 | - The type info for introspection can be accessed via ``Point2D.__annotations__``, | ||
| 1473 | - ``Point2D.__total__``, ``Point2D.__required_keys__``, and | ||
| 1474 | - ``Point2D.__optional_keys__``. | ||
| 1475 | 1472 | To allow using this feature with older versions of Python that do not | |
| 1476 | 1473 | support :pep:`526`, ``TypedDict`` supports two additional equivalent | |
| 1477 | 1474 | syntactic forms: | |
@@ -1488,6 +1485,18 @@ These are not used in annotations. They are building blocks for declaring types. | |||
| 1488 | 1485 | The keyword-argument syntax is deprecated in 3.11 and will be removed | |
| 1489 | 1486 | in 3.13. It may also be unsupported by static type checkers. | |
| 1490 | 1487 | ||
| 1488 | + The functional syntax should also be used when any of the keys are not valid | ||
| 1489 | + :ref:`identifiers`, for example because they are keywords or contain hyphens. | ||
| 1490 | + Example:: | ||
| 1491 | + | ||
| 1492 | + # raises SyntaxError | ||
| 1493 | + class Point2D(TypedDict): | ||
| 1494 | + in: int # 'in' is a keyword | ||
| 1495 | + x-y: int # name with hyphens | ||
| 1496 | + | ||
| 1497 | + # OK, functional syntax | ||
| 1498 | + Point2D = TypedDict('Point2D', {'in': int, 'x-y': int}) | ||
| 1499 | + | ||
| 1491 | 1500 | By default, all keys must be present in a ``TypedDict``. It is possible to | |
| 1492 | 1501 | override this by specifying totality. | |
| 1493 | 1502 | Usage:: | |
@@ -1504,6 +1513,82 @@ These are not used in annotations. They are building blocks for declaring types. | |||
| 1504 | 1513 | ``True`` as the value of the ``total`` argument. ``True`` is the default, | |
| 1505 | 1514 | and makes all items defined in the class body required. | |
| 1506 | 1515 | ||
| 1516 | + It is possible for a ``TypedDict`` type to inherit from one or more other ``TypedDict`` types | ||
| 1517 | + using the class-based syntax. | ||
| 1518 | + Usage:: | ||
| 1519 | + | ||
| 1520 | + class Point3D(Point2D): | ||
| 1521 | + z: int | ||
| 1522 | + | ||
| 1523 | + ``Point3D`` has three items: ``x``, ``y`` and ``z``. It is equivalent to this | ||
| 1524 | + definition:: | ||
| 1525 | + | ||
| 1526 | + class Point3D(TypedDict): | ||
| 1527 | + x: int | ||
| 1528 | + y: int | ||
| 1529 | + z: int | ||
| 1530 | + | ||
| 1531 | + A ``TypedDict`` cannot inherit from a non-TypedDict class, | ||
| 1532 | + notably including :class:`Generic`. For example:: | ||
| 1533 | + | ||
| 1534 | + class X(TypedDict): | ||
| 1535 | + x: int | ||
| 1536 | + | ||
| 1537 | + class Y(TypedDict): | ||
| 1538 | + y: int | ||
| 1539 | + | ||
| 1540 | + class Z(object): pass # A non-TypedDict class | ||
| 1541 | + | ||
| 1542 | + class XY(X, Y): pass # OK | ||
| 1543 | + | ||
| 1544 | + class XZ(X, Z): pass # raises TypeError | ||
| 1545 | + | ||
| 1546 | + T = TypeVar('T') | ||
| 1547 | + class XT(X, Generic[T]): pass # raises TypeError | ||
| 1548 | + | ||
| 1549 | + A ``TypedDict`` can be introspected via annotations dicts | ||
| 1550 | + (see :ref:`annotations-howto` for more information on annotations best practices), | ||
| 1551 | + :attr:`__total__`, :attr:`__required_keys__`, and :attr:`__optional_keys__`. | ||
| 1552 | + | ||
| 1553 | + .. attribute:: __total__ | ||
| 1554 | + | ||
| 1555 | + ``Point2D.__total__`` gives the value of the ``total`` argument. | ||
| 1556 | + Example:: | ||
| 1557 | + | ||
| 1558 | + >>> from typing import TypedDict | ||
| 1559 | + >>> class Point2D(TypedDict): pass | ||
| 1560 | + >>> Point2D.__total__ | ||
| 1561 | + True | ||
| 1562 | + >>> class Point2D(TypedDict, total=False): pass | ||
| 1563 | + >>> Point2D.__total__ | ||
| 1564 | + False | ||
| 1565 | + >>> class Point3D(Point2D): pass | ||
| 1566 | + >>> Point3D.__total__ | ||
| 1567 | + True | ||
| 1568 | + | ||
| 1569 | + .. attribute:: __required_keys__ | ||
| 1570 | + .. attribute:: __optional_keys__ | ||
| 1571 | + | ||
| 1572 | + ``Point2D.__required_keys__`` and ``Point2D.__optional_keys__`` return | ||
| 1573 | + :class:`frozenset` objects containing required and non-required keys, respectively. | ||
| 1574 | + Currently the only way to declare both required and non-required keys in the | ||
| 1575 | + same ``TypedDict`` is mixed inheritance, declaring a ``TypedDict`` with one value | ||
| 1576 | + for the ``total`` argument and then inheriting it from another ``TypedDict`` with | ||
| 1577 | + a different value for ``total``. | ||
| 1578 | + Usage:: | ||
| 1579 | + | ||
| 1580 | + >>> class Point2D(TypedDict, total=False): | ||
| 1581 | + ... x: int | ||
| 1582 | + ... y: int | ||
| 1583 | + ... | ||
| 1584 | + >>> class Point3D(Point2D): | ||
| 1585 | + ... z: int | ||
| 1586 | + ... | ||
| 1587 | + >>> Point3D.__required_keys__ == frozenset({'z'}) | ||
| 1588 | + True | ||
| 1589 | + >>> Point3D.__optional_keys__ == frozenset({'x', 'y'}) | ||
| 1590 | + True | ||
| 1591 | + | ||
| 1507 | 1592 | See :pep:`589` for more examples and detailed rules of using ``TypedDict``. | |
| 1508 | 1593 | ||
| 1509 | 1594 | .. versionadded:: 3.8 | |
| Back | FazBrowse Home | New Git URL |
0 commit comments