Reputation: 2922
If I have a Python module like this:
from abc import ABC, abstractmethod
class AbstractClass(ABC):
@abstractmethod
def method(self):
pass
class ConcreteClass1(AbstractClass):
def method(self):
print("hello")
class ConcreteClass2(AbstractClass):
def method(self):
print("hello")
class ConcreteClass3(AbstractClass):
def method(self):
print("hello")
classes = [
ConcreteClass1,
ConcreteClass2,
ConcreteClass3,
]
for c in classes:
c().method()
And I hit it with mypy test.py
, I get this:
test.py:27: error: Cannot instantiate abstract class "AbstractClass" with abstract attribute "method"
The code runs without any issues though, and I can't see any issues in the logic.
At no point am I trying to instantiate the AbstractClass
directly.
Some weird behavior I've noticed:
If, instead of a loop, I do this:
...
ConcreteClass1().method()
ConcreteClass2().method()
ConcreteClass3().method()
mypy is happy.
Also, if, instead of 3 classes in the loop, I do 2:
classes = [
ConcreteClass1,
ConcreteClass2,
#ConcreteClass3,
]
for c in classes:
c().method()
mypy is happy with that as well. What's going on? Is this a mypy bug? If so, can I tell mypy to ignore this "problem"?
Upvotes: 5
Views: 700
Reputation: 5387
The problem appears similar to mypy issues with abstract classes and dictionaries - for some reason, mypy can't typecheck this properly without a type annotation on the list:
classes: list[Type[AbstractClass]] = [
ConcreteClass1,
ConcreteClass2,
ConcreteClass3,
]
(Change list
to List
if you're on Python 3.8 or below)
You might want to file an issue for this bug on the mypy Github.
Upvotes: 5