Why Does Python Abstractmethod Not Raise an Exception?

I have been reading the Python documentation about abstract base classes and the @abstractmethod decorator. According to the documentation:

  • The @abstractmethod decorator indicates that a method is abstract and must be implemented in a subclass.
  • This requires that the class’s metaclass be ABCMeta or derived from it. A class with a metaclass derived from ABCMeta cannot be instantiated unless all its abstract methods are overridden.

I tried testing it with the following code:

import abc

class AbstractClass(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def abstractMethod(self):
        return

class ConcreteClass(AbstractClass):
    def __init__(self):
        self.me = "me"

c = ConcreteClass()
c.abstractMethod()

The code runs without any issue, and I don’t understand why. If I type c.abstractMethod, I get:

<bound method ConcreteClass.abstractMethod of <__main__.ConcreteClass object at 0x7f694da1c3d0>>

Why isn’t there an exception raised? I thought Python abstractmethod would require ConcreteClass to implement the abstract method, but no exception is raised. What am I missing here?

Hi there! I’ve worked with Python abstractmethod quite a bit, so let me help clarify this for you.

In Python 3, a recommended approach is to inherit directly from abc.ABC, which automatically sets the correct metaclass (ABCMeta). This ensures the enforcement of abstract methods without ambiguity. Here’s how it looks:

import abc

class AbstractClass(abc.ABC):  # Directly inherit from ABC
    @abc.abstractmethod
    def abstractMethod(self):
        return

class ConcreteClass(AbstractClass):
    def __init__(self):
        self.me = "me"
    
    # Implement the abstract method
    def abstractMethod(self):
        print("Implemented in ConcreteClass")

c = ConcreteClass()
c.abstractMethod()  # Output: "Implemented in ConcreteClass"

By explicitly inheriting from abc.ABC, you ensure that Python properly enforces the abstractMethod. If the abstract method isn’t implemented in ConcreteClass, Python will throw a TypeError when you try to instantiate it.

Good point, Archana! Building on that, it’s important to check if all abstract methods are implemented in the subclass.

If the base class has multiple abstract methods, the subclass must implement all of them. Otherwise, Python will raise a TypeError. Here’s an example:

import abc

class AbstractClass(abc.ABC):
    @abc.abstractmethod
    def abstractMethod(self):
        return

    @abc.abstractmethod
    def anotherAbstractMethod(self):
        return

class ConcreteClass(AbstractClass):
    def __init__(self):
        self.me = "me"

    def abstractMethod(self):
        pass  # Implementing the first abstract method

    def anotherAbstractMethod(self):
        pass  # Implementing the second abstract method

c = ConcreteClass()  # No error because all abstract methods are implemented

If you omit even one abstract method in the subclass, instantiating ConcreteClass will immediately throw an error. This strictness is by design—Python abstractmethod ensures adherence to the contract defined in the base class.

Great insights so far! I’d like to add a quick note about Python versions, as that can be a common pitfall.

If you’re working with an older Python version (e.g., Python 2.x), the behavior of abc.ABCMeta and the @abstractmethod decorator might differ. For Python 3.x, you should inherit from abc.ABC, as shown in earlier examples. However, in Python 2.x, you’d use __metaclass__ = abc.ABCMeta. Here’s how it works:

import abc

class AbstractClass(object):
    __metaclass__ = abc.ABCMeta  # Required in Python 2.x

    @abc.abstractmethod
    def abstractMethod(self):
        return

class ConcreteClass(AbstractClass):
    def __init__(self):
        self.me = "me"

    def abstractMethod(self):
        print("Implemented for Python 2 compatibility")

c = ConcreteClass()  # No error if abstractMethod is implemented

Always check your Python version (python --version) to ensure compatibility. For modern projects, sticking with Python 3.x and abc.ABC is strongly recommended—it simplifies handling of Python abstractmethod and makes your code more future-proof.