@@ -178,27 +178,35 @@ override has a compatible signature:
178
178
179
179
.. code-block :: python
180
180
181
- class A :
181
+ class Base :
182
182
def f (self , x : int ) -> None :
183
183
...
184
184
185
- class B ( A ):
185
+ class Derived1 ( Base ):
186
186
def f (self , x : str ) -> None : # Error: type of 'x' incompatible
187
187
...
188
188
189
- class C ( A ):
189
+ class Derived2 ( Base ):
190
190
def f (self , x : int , y : int ) -> None : # Error: too many arguments
191
191
...
192
192
193
- class D ( A ):
193
+ class Derived3 ( Base ):
194
194
def f (self , x : int ) -> None : # OK
195
195
...
196
196
197
+ class Derived4 (Base ):
198
+ def f (self , x : float ) -> None : # OK: mypy treats int as a subtype of float
199
+ ...
200
+
201
+ class Derived5 (Base ):
202
+ def f (self , x : int , y : int = 0 ) -> None : # OK: accepts more than the base
203
+ ... # class method
204
+
197
205
.. note ::
198
206
199
207
You can also vary return types **covariantly ** in overriding. For
200
- example, you could override the return type ``object `` with a subtype
201
- such as ``int ``. Similarly, you can vary argument types
208
+ example, you could override the return type ``Iterable[int] `` with a
209
+ subtype such as ``List[ int] ``. Similarly, you can vary argument types
202
210
**contravariantly ** -- subclasses can have more general argument types.
203
211
204
212
You can also override a statically typed method with a dynamically
@@ -213,50 +221,103 @@ effect at runtime:
213
221
214
222
.. code-block :: python
215
223
216
- class A :
224
+ class Base :
217
225
def inc (self , x : int ) -> int :
218
226
return x + 1
219
227
220
- class B ( A ):
228
+ class Derived ( Base ):
221
229
def inc (self , x ): # Override, dynamically typed
222
- return ' hello' # Incompatible with 'A ', but no mypy error
230
+ return ' hello' # Incompatible with 'Base ', but no mypy error
223
231
224
232
Abstract base classes and multiple inheritance
225
233
**********************************************
226
234
227
235
Mypy supports Python abstract base classes (ABCs). Abstract classes
228
236
have at least one abstract method or property that must be implemented
229
- by a subclass. You can define abstract base classes using the
230
- ``abc.ABCMeta `` metaclass, and the ``abc.abstractmethod `` and
231
- `` abc.abstractproperty `` function decorators . Example:
237
+ by any * concrete * (non-abstract) subclass. You can define abstract base
238
+ classes using the ``abc.ABCMeta `` metaclass and the ``abc.abstractmethod ``
239
+ function decorator . Example:
232
240
233
241
.. code-block :: python
234
242
235
243
from abc import ABCMeta, abstractmethod
236
244
237
- class A (metaclass = ABCMeta ):
245
+ class Animal (metaclass = ABCMeta ):
238
246
@abstractmethod
239
- def foo (self , x : int ) -> None : pass
247
+ def eat (self , food : str ) -> None : pass
240
248
249
+ @ property
241
250
@abstractmethod
242
- def bar (self ) -> str : pass
251
+ def can_walk (self ) -> bool : pass
252
+
253
+ class Cat (Animal ):
254
+ def eat (self , food : str ) -> None :
255
+ ... # Body omitted
243
256
244
- class B (A ):
245
- def foo (self , x : int ) -> None : ...
246
- def bar (self ) -> str :
247
- return ' x'
257
+ @ property
258
+ def can_walk (self ) -> bool :
259
+ return True
248
260
249
- a = A() # Error: 'A' is abstract
250
- b = B() # OK
261
+ x = Animal() # Error: 'Animal' is abstract due to 'eat' and 'can_walk'
262
+ y = Cat() # OK
263
+
264
+ .. note ::
265
+
266
+ In Python 2.7 you have to use ``@abc.abstractproperty `` to define
267
+ an abstract property.
251
268
252
269
Note that mypy performs checking for unimplemented abstract methods
253
270
even if you omit the ``ABCMeta `` metaclass. This can be useful if the
254
271
metaclass would cause runtime metaclass conflicts.
255
272
273
+ Since you can't create instances of ABCs, they are most commonly used in
274
+ type annotations. For example, this method accepts arbitrary iterables
275
+ containing arbitrary animals (instances of concrete ``Animal ``
276
+ subclasses):
277
+
278
+ .. code-block :: python
279
+
280
+ def feed_all (animals : Iterable[Animal], food : str ) -> None :
281
+ for animal in animals:
282
+ animal.eat(food)
283
+
284
+ There is one important peculiarity about how ABCs work in Python --
285
+ whether a particular class is abstract or not is somewhat implicit.
286
+ In the example below, ``Derived `` is treated as an abstract base class
287
+ since ``Derived `` inherits an abstract ``f `` method from ``Base `` and
288
+ doesn't explicitly implement it. The definition of ``Derived ``
289
+ generates no errors from mypy, since it's a valid ABC:
290
+
291
+ .. code-block :: python
292
+
293
+ from abc import ABCMeta, abstractmethod
294
+
295
+ class Base (metaclass = ABCMeta ):
296
+ @abstractmethod
297
+ def f (self , x : int ) -> None : pass
298
+
299
+ class Derived (Base ): # No error -- Derived is implicitly abstract
300
+ def g (self ) -> None :
301
+ ...
302
+
303
+ Attempting to create an instance of ``Derived `` will be rejected,
304
+ however:
305
+
306
+ .. code-block :: python
307
+
308
+ d = Derived() # Error: 'Derived' is abstract
309
+
310
+ .. note ::
311
+
312
+ It's a common error to forget to implement an abstract method.
313
+ As shown above, the class definition will not generate an error
314
+ in this case, but any attempt to construct an instance will be
315
+ flagged as an error.
316
+
256
317
A class can inherit any number of classes, both abstract and
257
318
concrete. As with normal overrides, a dynamically typed method can
258
- implement a statically typed method defined in any base class,
259
- including an abstract method defined in an abstract base class.
319
+ override or implement a statically typed method defined in any base
320
+ class, including an abstract method defined in an abstract base class.
260
321
261
322
You can implement an abstract property using either a normal
262
323
property or an instance variable.
0 commit comments