Abstract Base Classes

Use abc.ABC to define a contract that subclasses must fulfil — enforced at instantiation time.

An abstract base class (ABC) defines a contract: it declares methods that must exist, but leaves the implementation to subclasses. Try to instantiate a class that has not implemented all the abstract methods and Python raises a TypeError immediately — no silent half-built objects.

The recipe

Inherit from abc.ABC and decorate the required methods with @abstractmethod.

from abc import ABC, abstractmethod

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

# Shape() -> TypeError: Can't instantiate abstract class
class Square(Shape):
    def __init__(self, side):
        self.side = side
    def area(self):
        return self.side ** 2

print(Square(4).area())   # 16

Why bother?

ABCs give you fail-fast guarantees. If a teammate adds a new Shape subclass and forgets area(), they find out the moment they try to create one — not three modules later when something calls the missing method. You can also mix in concrete helper methods that build on the abstract ones.

Example

Example · python
from abc import ABC, abstractmethod

class PaymentProcessor(ABC):
    """Every processor must know how to charge; refund is optional-with-default."""

    @abstractmethod
    def charge(self, amount_cents: int) -> str:
        ...

    # A concrete method built on top of the abstract one
    def charge_with_receipt(self, amount_cents: int) -> str:
        ref = self.charge(amount_cents)
        return f'Charged ${amount_cents/100:.2f} [ref {ref}]'

class StripeProcessor(PaymentProcessor):
    def charge(self, amount_cents: int) -> str:
        return f'stripe_{amount_cents}'

class BrokenProcessor(PaymentProcessor):
    pass   # forgot to implement charge()

print(StripeProcessor().charge_with_receipt(2599))

try:
    BrokenProcessor()          # fails at construction, not at call time
except TypeError as e:
    print('blocked:', str(e).split(' with')[0])

print('is a subclass?', issubclass(StripeProcessor, PaymentProcessor))

# Output:
# Charged $25.99 [ref stripe_2599]
# blocked: Can't instantiate abstract class BrokenProcessor
# is a subclass? True

When to use it

  • A plugin system defines an abstract Exporter base class so all plugins must implement export().
  • A storage layer defines an abstract Repository with find() and save() that SQL and Redis backends implement.
  • A payment gateway enforces that every provider class implements charge() and refund() or fails at instantiation.

More examples

Define and implement an ABC

Defines an abstract Shape class; instantiating it directly fails, but Square implements the required area().

Example · python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self) -> float: ...

class Square(Shape):
    def __init__(self, side): self.side = side
    def area(self): return self.side ** 2

print(Square(4).area())   # 16
# Shape()  -> TypeError: Can't instantiate abstract class

Multiple abstract methods

Shows a Repository ABC with two abstract methods that the InMemoryRepo must implement.

Example · python
from abc import ABC, abstractmethod

class Repository(ABC):
    @abstractmethod
    def find(self, id: int): ...

    @abstractmethod
    def save(self, obj) -> None: ...

class InMemoryRepo(Repository):
    def __init__(self): self._store = {}
    def find(self, id): return self._store.get(id)
    def save(self, obj): self._store[obj['id']] = obj

repo = InMemoryRepo()
repo.save({'id': 1, 'name': 'Alice'})
print(repo.find(1))

isinstance check with ABC

Demonstrates that isinstance() returns True for the ABC, enabling type-safe dispatch.

Example · python
from abc import ABC, abstractmethod

class Serialisable(ABC):
    @abstractmethod
    def to_dict(self) -> dict: ...

class User(Serialisable):
    def __init__(self, name): self.name = name
    def to_dict(self): return {'name': self.name}

u = User('Bob')
print(isinstance(u, Serialisable))   # True
print(u.to_dict())                   # {'name': 'Bob'}

Discussion

  • Be the first to comment on this lesson.