How do abstract base classes and protocols enforce interfaces in Python?

· Category: Python Programming

Short answer

Abstract base classes (ABCs) from the abc module enforce that subclasses implement specific methods. typing.Protocol provides structural subtyping, allowing you to define interfaces without explicit inheritance.

Steps

  1. Inherit from abc.ABC and decorate abstract methods with @abstractmethod.
  2. Subclass the ABC and implement all abstract methods.
  3. Alternatively, define a typing.Protocol class with method stubs.
from abc import ABC, abstractmethod

class Drawable(ABC):
    @abstractmethod
    def draw(self):
        pass

class Circle(Drawable):
    def draw(self):
        print("Drawing a circle")

# Protocol
from typing import Protocol

class Runnable(Protocol):
    def run(self) -> None:
        ...

class Task:
    def run(self):
        print("Running task")

def execute(r: Runnable):
    r.run()

execute(Task())

Tips

  • ABCs prevent instantiation of incomplete classes, catching errors early.
  • Protocol is ideal for duck typing with static type checkers like mypy.
  • collections.abc provides many useful ABCs like Sequence, Mapping, and Callable.

Common issues

  • Forgetting @abstractmethod means the method is optional, defeating the purpose of the ABC.
  • ABCs add a small runtime overhead compared to plain classes.
  • Protocol checks are enforced by static type checkers, not at runtime (unless explicitly checked with isinstance() and @runtime_checkable).