環境
- Python 3.11.2
- mypy 1.2.0
起きたこと
抽象基底クラスAnimal
を継承しているCat
クラスでは、cry
メソッドの実装が漏れていました。
import abc
class Animal(abc.ABC):
@abc.abstractmethod
def cry(self) -> None:
pass
class Dog(Animal):
def cry(self) -> None:
print("bowwow")
def only_dog_method(self) -> None:
print("only dog method")
class Cat(Animal):
# cryメソッドの実装漏れ
def only_cat_method(self) -> None:
print("only cat method")
この状態でmypyを実行してもエラーは発生しません。なぜでしょうか?
$ mypy sample.py
Success: no issues found in 1 source file
原因
コードを書いている私は、Cat
クラスを具象クラスとして扱っていましたが、mypyはCat
が抽象基底クラスか具象クラスか判断できません。mypyはCat
クラスを抽象基底クラスとして扱っているため、エラーは発生しませんでした。
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 class since Derived inherits an abstract f method from Base and doesn’t explicitly implement it. The definition of Derived generates no errors from mypy, since it’s a valid ABC:
解決策
インスタンスを生成すれば、mypyはエラーを出力します。
...
dog = Dog()
cat = Cat()
$ mypy sample.py
sample.py:26: error: Cannot instantiate abstract class "Cat" with abstract attribute "cry" [abstract]
Found 1 error in 1 file (checked 1 source file)
もちろん、Python実行時にエラーも発生します。
$ python sample.py
Traceback (most recent call last):
File "/home/vagrant/Documents/study/20230503/sample.py", line 26, in <module>
cat = Cat()
^^^^^
TypeError: Can't instantiate abstract class Cat with abstract method cry