Python abstract classes and interfaces
abc module, ABC class, @abstractmethod, abstract properties, interface pattern, why abstract classes matter, NotImplementedError alternative
Abstract Classes
An abstract class defines a contract — methods that all subclasses must implement. You cannot instantiate an abstract class directly. Use the abc module.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float:
"""Return the area of the shape."""
...
@abstractmethod
def perimeter(self) -> float:
...
def describe(self):
print(f"Area: {self.area():.2f}, Perimeter: {self.perimeter():.2f}")
class Rectangle(Shape):
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
def perimeter(self):
return 2 * (self.w + self.h)
r = Rectangle(4, 5)
r.describe() # Area: 20.00, Perimeter: 18.00
# Shape() → TypeError: cannot instantiate abstract class
Why Use ABC
Without @abstractmethod, a subclass that forgets to implement a method will not raise an error until that method is actually called. With it, the error is raised immediately at instantiation — catching the bug earlier. Non-abstract methods in the base class are inherited normally.
Abstract classes enforce a contract at the class design level, not the runtime level. They document intent: subclasses of Shape must provide area and perimeter. This is especially valuable in team settings where multiple developers implement different subclasses independently. Python's abc module also supports abstract properties and abstract class methods. Protocols (from typing) are an alternative structural-typing approach — an object satisfies a Protocol if it has the required methods, without needing to explicitly inherit, following Python's duck-typing philosophy.
