CodeNebula
Python🚀Advancedadvanced

Abstract Base Classes (ABCs)

Python · Advanced · Run with python3

Explanation

`abc.ABC` (or `metaclass=abc.ABCMeta`) lets you define interfaces that subclasses must implement. Methods decorated with `@abstractmethod` must be overridden — instantiating a class with unimplemented abstract methods raises `TypeError`. ABCs also support `register()` for virtual subclass registration: `ABC.register(SomeClass)` makes `isinstance(obj, ABC)` return `True` without inheritance. The `collections.abc` module defines ABCs for built-in protocols (`Iterable`, `Mapping`, `Sequence`).

Real-World Scenario

A plugin architecture defines `class DataSource(ABC)` with abstract methods `connect()`, `read_batch()`, `close()`. Each data connector (S3, Kafka, Postgres) implements the interface. Application code depends only on `DataSource` — swapping connectors requires no changes. ```python from abc import ABC, abstractmethod from typing import Iterator class DataSource(ABC): @abstractmethod def connect(self) -> None: ... @abstractmethod def read_batch(self, size: int) -> list[dict]: ... @abstractmethod def close(self) -> None: ... def read_all(self, batch_size: int = 100) -> Iterator[list[dict]]: """Template method — uses abstract read_batch.""" self.connect() try: while batch := self.read_batch(batch_size): yield batch finally: self.close() class MemorySource(DataSource): def __init__(self, data: list[dict]): self._data = data self._pos = 0 def connect(self) -> None: pass def close(self) -> None: pass def read_batch(self, size: int) -> list[dict]: batch = self._data[self._pos:self._pos + size] self._pos += size return batch src = MemorySource([{"id": i} for i in range(5)]) for batch in src.read_all(batch_size=2): print(batch) ```

Quick Snippet

snippet.py
from abc import ABC, abstractmethod
from typing import Iterator

class DataSource(ABC):
    @abstractmethod
    def connect(self) -> None: ...

    @abstractmethod
    def read_batch(self, size: int) -> list[dict]: ...

    @abstractmethod
    def close(self) -> None: ...

    def read_all(self, batch_size: int = 100) -> Iterator[list[dict]]:
        """Template method — uses abstract read_batch."""
        self.connect()
        try:
            while batch := self.read_batch(batch_size):
                yield batch
        finally:
            self.close()

class MemorySource(DataSource):
    def __init__(self, data: list[dict]):
        self._data = data
        self._pos = 0

    def connect(self) -> None: pass
    def close(self) -> None:   pass

    def read_batch(self, size: int) -> list[dict]:
        batch = self._data[self._pos:self._pos + size]
        self._pos += size
        return batch

src = MemorySource([{"id": i} for i in range(5)])
for batch in src.read_all(batch_size=2):
    print(batch)

Full Example

abstract_base_classes.py
# Compile: python3 abstract_base_classes.py
# Output:
# {'id': 0}
# {'id': 1}
# {'id': 2}

from abc import ABC, abstractmethod
from typing import Iterator

class DataSource(ABC):
    @abstractmethod
    def connect(self) -> None: ...

    @abstractmethod
    def read_batch(self, size: int) -> list[dict]: ...

    @abstractmethod
    def close(self) -> None: ...

    def read_all(self, batch_size: int = 2) -> Iterator[list[dict]]:
        self.connect()
        try:
            while batch := self.read_batch(batch_size):
                yield batch
        finally:
            self.close()

class MemorySource(DataSource):
    def __init__(self, data: list[dict]):
        self._data = data
        self._pos = 0

    def connect(self) -> None: pass
    def close(self) -> None:   pass

    def read_batch(self, size: int) -> list[dict]:
        batch = self._data[self._pos:self._pos + size]
        self._pos += size
        return batch

src = MemorySource([{"id": i} for i in range(5)])
for batch in src.read_all(batch_size=2):
    for row in batch:
        print(row)

# Can't instantiate ABC with unimplemented methods
try:
    DataSource()
except TypeError as e:
    print(f"Cannot instantiate: {e}")
Run command
python3 abstract_base_classes.py