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
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
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
Rectangle: area=12.00, perimeter=14.00
Circle: area=12.57, perimeter=12.57
Error: Can't instantiate abstract class Shape6. 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
1. What happens when you try to instantiate a class that inherits from ABC but hasn't overridden all its @abstractmethod methods?
2. Which module provides ABC and @abstractmethod in Python's standard library?
3. In the Shape example, why does Shape() raise a TypeError?
4. Does Python's abc module check that an overriding method's parameters match the abstract method's signature?
5. If a base class method simply does 'raise NotImplementedError' but the class does NOT inherit from ABC, what happens when you instantiate it without overriding that method?
6. Can an abstract base class (using ABC) include fully implemented, non-abstract methods?
Was this page helpful?
You May Also Like
Encapsulation in Python
How Python bundles data and methods together and uses naming conventions and name mangling to signal restricted access.
Abstraction in Python
How Python hides implementation complexity behind simple interfaces, using the abc module to enforce required methods.
Inheritance in Python
How subclasses reuse and extend behavior from parent classes, and how super() and MRO resolve method lookups.
Multiple Inheritance in Python
How Python resolves method lookups across multiple parent classes using MRO (Method Resolution Order) and C3 linearization, including the diamond problem.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics