Abstract base classes and multiple inheritance
Mypy supports Python abstract base classes (ABCs). Abstract classeshave at least one abstract method or property that must be implementedby any concrete (non-abstract) subclass. You can define abstract baseclasses using the abc.ABCMeta
metaclass and the @abc.abstractmethod
function decorator. Example:
- from abc import ABCMeta, abstractmethod
- class Animal(metaclass=ABCMeta):
- @abstractmethod
- def eat(self, food: str) -> None: pass
- @property
- @abstractmethod
- def can_walk(self) -> bool: pass
- class Cat(Animal):
- def eat(self, food: str) -> None:
- ... # Body omitted
- @property
- def can_walk(self) -> bool:
- return True
- x = Animal() # Error: 'Animal' is abstract due to 'eat' and 'can_walk'
- y = Cat() # OK
Note
In Python 2.7 you have to use @abc.abstractproperty
to definean abstract property.
Note that mypy performs checking for unimplemented abstract methodseven if you omit the ABCMeta
metaclass. This can be useful if themetaclass would cause runtime metaclass conflicts.
Since you can’t create instances of ABCs, they are most commonly used intype annotations. For example, this method accepts arbitrary iterablescontaining arbitrary animals (instances of concrete Animal
subclasses):
- def feed_all(animals: Iterable[Animal], food: str) -> None:
- for animal in animals:
- animal.eat(food)
There is one important peculiarity about how ABCs work in Python –whether a particular class is abstract or not is somewhat implicit.In the example below, Derived
is treated as an abstract base classsince Derived
inherits an abstract f
method from Base
anddoesn’t explicitly implement it. The definition of Derived
generates no errors from mypy, since it’s a valid ABC:
- from abc import ABCMeta, abstractmethod
- class Base(metaclass=ABCMeta):
- @abstractmethod
- def f(self, x: int) -> None: pass
- class Derived(Base): # No error -- Derived is implicitly abstract
- def g(self) -> None:
- ...
Attempting to create an instance of Derived
will be rejected,however:
- d = Derived() # Error: 'Derived' is abstract
Note
It’s a common error to forget to implement an abstract method.As shown above, the class definition will not generate an errorin this case, but any attempt to construct an instance will beflagged as an error.
A class can inherit any number of classes, both abstract andconcrete. As with normal overrides, a dynamically typed method canoverride or implement a statically typed method defined in any baseclass, including an abstract method defined in an abstract base class.
You can implement an abstract property using either a normalproperty or an instance variable.