|
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