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
@abstractmethod
to a method will not be accepted by Python if that class doesn't have ABCMeta
as metaclassI 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?
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.