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

Try it yourself
Loading editor…
Press Run to execute the code.

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.