5

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"?

John
  • 2,551
  • 3
  • 30
  • 55

1 Answers1

4

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.

SuperStormer
  • 4,997
  • 5
  • 25
  • 35
  • Awesome. Thanks. [Bug submitted](https://github.com/python/mypy/issues/12624). BTW, your `list` should be `List`. I tried to submit a correction, but apparently the stackoverflow `Suggested edit queue is full` – John Apr 19 '22 at 13:00
  • @John It's a new feature in Python 3.9. – SuperStormer Apr 19 '22 at 19:09
  • Oh I didn't know that. Awesome! Thanks – John Apr 20 '22 at 12:40