100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Abstract Classes in Python

Using the abc module to define abstract base classes and abstract methods that force subclasses to implement required behavior.

OOP AdvancedIntermediate11 min readJul 7, 2026
Analogies

1. Introduction

An abstract class is a class that is not meant to be instantiated directly — it exists to define a common interface (and possibly some shared implementation) that concrete subclasses must complete. Python provides the abc module for this: by inheriting from abc.ABC and marking methods with @abstractmethod, you tell Python to prevent instantiation of any subclass that hasn't overridden every abstract method.

🏏

Cricket analogy: The ICC's fast-bowler certification is like abc.ABC — a trainee can't be selected to bowl until every required drill, from the yorker to the bouncer, is signed off, just as @abstractmethod blocks an incomplete subclass.

This is useful for enforcing a contract across a family of related classes (e.g. all Shape subclasses must implement area() and perimeter()) and for documenting, at the type level, what a valid subclass must provide, catching incomplete implementations early with a clear error rather than a confusing AttributeError at runtime.

🏏

Cricket analogy: Just as every state team in the Ranji Trophy must field a wicketkeeper and an opening pair by rule, an abstract Shape class forces every subclass to implement area() and perimeter(), flagging a missing one immediately rather than failing mid-match.

2. Syntax

python
from abc import ABC, abstractmethod


class MyAbstractBase(ABC):
    @abstractmethod
    def required_method(self):
        """Subclasses MUST override this."""
        raise NotImplementedError

    def concrete_method(self):
        # Regular method — shared implementation, inherited as-is
        return "shared behavior"


class ConcreteImpl(MyAbstractBase):
    def required_method(self):
        return "implemented"

3. Explanation

An abstract base class inherits from abc.ABC (which uses the ABCMeta metaclass). Any method decorated with @abstractmethod must be overridden in every concrete (non-abstract) subclass. Abstract classes can still define regular (concrete) methods with real implementations, including ones that call self.some_abstract_method() — these become 'template methods' that rely on subclasses to fill in the specifics while reusing shared logic.

🏏

Cricket analogy: A team's standard pre-match routine (template method) always ends by calling 'execute the toss strategy,' a step each captain (subclass) must define themselves, just as a concrete method in an ABC calls self.some_abstract_method().

Abstract classes are about enforcing structure, not just documentation: attempting to instantiate a class with unimplemented abstract methods raises TypeError immediately at instantiation time. This is much easier to debug than a plain base class with 'raise NotImplementedError' placeholder methods, which only fails later when that specific method is actually called.

Gotcha: the abc module only prevents instantiation of a class that has unimplemented abstract methods — it does not enforce method signatures (parameter counts/types) matching between the abstract method and its override. Also, a class only counts as 'abstract' if the metaclass machinery (inheriting from ABC, or using metaclass=ABCMeta) is actually in place; simply raising NotImplementedError in a plain base class method does NOT block instantiation — Python happily creates the instance, and the error only surfaces when that particular method is called.

4. Example

python
from abc import ABC, abstractmethod


class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

    def describe(self):
        return f"{self.__class__.__name__}: area={self.area():.2f}, perimeter={self.perimeter():.2f}"


class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)


class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14159 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14159 * self.radius


shapes = [Rectangle(3, 4), Circle(2)]
for s in shapes:
    print(s.describe())

try:
    Shape()
except TypeError:
    print("Error: Can't instantiate abstract class Shape")

5. Output

text
Rectangle: area=12.00, perimeter=14.00
Circle: area=12.57, perimeter=12.57
Error: Can't instantiate abstract class Shape

6. Key Takeaways

  • Inherit from abc.ABC and decorate required methods with @abstractmethod to define an abstract base class.
  • Any subclass that doesn't override all abstract methods cannot be instantiated — Python raises TypeError.
  • Abstract classes can still provide concrete (shared) methods alongside abstract ones, enabling the template-method pattern.
  • abc enforces presence of overrides, not their signatures — parameter mismatches are not checked.
  • Simply raising NotImplementedError in a plain (non-ABC) base class does not prevent instantiation — it only fails when that method is actually called.
  • Abstract classes document and enforce a contract that all concrete subclasses must fulfill, catching incomplete implementations early.

Practice what you learned

Was this page helpful?

Topics covered

#Python#PythonProgrammingStudyNotes#Programming#AbstractClassesInPython#Abstract#Classes#Syntax#Explanation#OOP#StudyNotes#SkillVeris