Search code examples
pythonpython-3.xabstract-classabstract

Why can I instantiate classes with abstract methods in Python?


I noticed that a class with an abstractmethod can still be instantiated if it does not inherit from ABC. This seems to be in contrast with the documentation:

Using this decorator requires that the class’s metaclass is ABCMeta or is derived from it. A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.

From this I would understand that

  1. Adding @abstractmethod to a method will not be accepted by Python if that class doesn't have ABCMeta as metaclass
  2. Even if it is, that class can not be instantiated

I drafted the following example:

from abc import abstractmethod, ABC


class TestClassOne:
    @abstractmethod
    def test_method(self):
        ...


class TestClassTwo(ABC):
    @abstractmethod
    def test_method(self):
        ...


test_object_one = TestClassOne()
test_object_two = TestClassTwo()

Runnig on Python 3.9.13 or 3.11.3 gives the output

TypeError: Can't instantiate abstract class TestClassTwo with abstract method test_method

but notably this error does not mention TestClassOne.

Am I misunderstanding something here or could this be a bug in Python?


Solution

  • The ABCMeta metaclass and the @abstractmethod decorator work together to prevent instantiation of a class that doesn't implement the required methods. Each of them has no effect without the other.

    So if you define an abstract base class without any @abstractmethod decorators, it allows instantiation -- it's not really abstract.

    And if you use @abstractmethod in a non-ABC, it's ignored because it's the metaclass that actually implements the enforcement. This decorator simply registers the method as requiring an override in the subclass.