|
3 | 3 | Protocols and structural subtyping |
4 | 4 | ================================== |
5 | 5 |
|
6 | | -Mypy supports two ways of deciding whether two classes are compatible |
7 | | -as types: nominal subtyping and structural subtyping. |
8 | | - |
9 | | -*Nominal* subtyping is strictly based on the class hierarchy. If class ``D`` |
10 | | -inherits class ``C``, it's also a subtype of ``C``, and instances of |
11 | | -``D`` can be used when ``C`` instances are expected. This form of |
12 | | -subtyping is used by default in mypy, since it's easy to understand |
13 | | -and produces clear and concise error messages, and since it matches |
14 | | -how the native :py:func:`isinstance <isinstance>` check works -- based on class |
| 6 | +The Python type system supports two ways of deciding whether two objects are |
| 7 | +compatible as types: nominal subtyping and structural subtyping. |
| 8 | + |
| 9 | +*Nominal* subtyping is strictly based on the class hierarchy. If class ``Dog`` |
| 10 | +inherits class ``Animal``, it's a subtype of ``Animal``. Instances of ``Dog`` |
| 11 | +can be used when ``Animal`` instances are expected. This form of subtyping |
| 12 | +subtyping is what Python's type system predominantly uses: it's easy to |
| 13 | +understand and produces clear and concise error messages, and matches how the |
| 14 | +native :py:func:`isinstance <isinstance>` check works -- based on class |
15 | 15 | hierarchy. |
16 | 16 |
|
17 | | -*Structural* subtyping is based on the operations that can be performed with an object. Class ``D`` is |
18 | | -a structural subtype of class ``C`` if the former has all attributes |
19 | | -and methods of the latter, and with compatible types. |
| 17 | +*Structural* subtyping is based on the operations that can be performed with an |
| 18 | +object. Class ``Dog`` is a structural subtype of class ``Animal`` if the former |
| 19 | +has all attributes and methods of the latter, and with compatible types. |
20 | 20 |
|
21 | | -Structural subtyping can be seen as a static equivalent of duck |
22 | | -typing, which is well known to Python programmers. Mypy provides |
23 | | -support for structural subtyping via protocol classes described |
24 | | -below. See :pep:`544` for the detailed specification of protocols |
25 | | -and structural subtyping in Python. |
| 21 | +Structural subtyping can be seen as a static equivalent of duck typing, which is |
| 22 | +well known to Python programmers. See :pep:`544` for the detailed specification |
| 23 | +of protocols and structural subtyping in Python. |
26 | 24 |
|
27 | 25 | .. _predefined_protocols: |
28 | 26 |
|
@@ -60,8 +58,7 @@ For example, ``IntList`` below is iterable, over ``int`` values: |
60 | 58 |
|
61 | 59 | :ref:`predefined_protocols_reference` lists all protocols defined in |
62 | 60 | :py:mod:`typing` and the signatures of the corresponding methods you need to define |
63 | | -to implement each protocol (the signatures can be left out, as always, but mypy |
64 | | -won't type check unannotated methods). |
| 61 | +to implement each protocol. |
65 | 62 |
|
66 | 63 | Simple user-defined protocols |
67 | 64 | ***************************** |
@@ -89,18 +86,12 @@ class: |
89 | 86 | for item in items: |
90 | 87 | item.close() |
91 | 88 |
|
92 | | - close_all([Resource(), open('some/file')]) # Okay! |
| 89 | + close_all([Resource(), open('some/file')]) # OK |
93 | 90 |
|
94 | 91 | ``Resource`` is a subtype of the ``SupportsClose`` protocol since it defines |
95 | 92 | a compatible ``close`` method. Regular file objects returned by :py:func:`open` are |
96 | 93 | similarly compatible with the protocol, as they support ``close()``. |
97 | 94 |
|
98 | | -.. note:: |
99 | | - |
100 | | - The ``Protocol`` base class is provided in the ``typing_extensions`` |
101 | | - package for Python 3.4-3.7. Starting with Python 3.8, ``Protocol`` |
102 | | - is included in the ``typing`` module. |
103 | | - |
104 | 95 | Defining subprotocols and subclassing protocols |
105 | 96 | *********************************************** |
106 | 97 |
|
@@ -171,6 +162,13 @@ abstract: |
171 | 162 | ExplicitSubclass() # error: Cannot instantiate abstract class 'ExplicitSubclass' |
172 | 163 | # with abstract attributes 'attr' and 'method' |
173 | 164 |
|
| 165 | +Similarly, explicitly assigning to a protocol instance can be a way to ask the |
| 166 | +type checker to verify that your class implements a protocol: |
| 167 | + |
| 168 | +.. code-block:: python |
| 169 | +
|
| 170 | + _proto: SomeProto = cast(ExplicitSubclass, None) |
| 171 | +
|
174 | 172 | Invariance of protocol attributes |
175 | 173 | ********************************* |
176 | 174 |
|
|
0 commit comments