Site Tools


python-abc

Table of Contents

Python ABC

Python ABC (Abstract Base Classes) from the abc module let you define classes that can't be instantiated directly and require subclasses to implement specific methods. They enforce interface contracts without the overhead of multiple inheritance, making it clear what methods subclasses must provide.

Use ABCs to define plugin interfaces, enforce method implementation, or document expected behavior for subclasses.

Example

This example shows ABCs enforcing method implementation and interface contracts.

# run: python3 abc.py
# description: abstract base classes for interface enforcement
 
from abc import ABC, abstractmethod
 
class Handler(ABC):
    """Abstract handler that subclasses must implement."""
 
    @abstractmethod
    def handle(self, data):
        """Process data. Subclasses must implement."""
        pass
 
    @abstractmethod
    def validate(self, data):
        """Validate data format. Subclasses must implement."""
        pass
 
    def process(self, data):
        """Template method: validate then handle."""
        if self.validate(data):
            return self.handle(data)
        raise ValueError("Invalid data")
 
# Can't instantiate ABC directly
try:
    h = Handler()
except TypeError as e:
    print(f"Error: {e}")
 
# Subclass must implement all abstract methods
class JsonHandler(Handler):
    def handle(self, data):
        return f"Handled JSON: {data}"
 
    def validate(self, data):
        return isinstance(data, dict)
 
class CsvHandler(Handler):
    def handle(self, data):
        return f"Handled CSV: {data}"
 
    def validate(self, data):
        return isinstance(data, str)
 
# Instantiation works now
json_h = JsonHandler()
csv_h = CsvHandler()
 
print(f"JSON: {json_h.process({'key': 'value'})}")
print(f"CSV: {csv_h.process('a,b,c')}")
 
# Abstract properties
class Database(ABC):
    @property
    @abstractmethod
    def connection_string(self):
        """Subclasses must implement this property."""
        pass
 
    @classmethod
    @abstractmethod
    def from_config(cls, config):
        """Factory method subclasses must implement."""
        pass
 
class PostgresDB(Database):
    @property
    def connection_string(self):
        return "postgresql://localhost/db"
 
    @classmethod
    def from_config(cls, config):
        return cls()
 
db = PostgresDB()
print(f"Connection: {db.connection_string}")

Common patterns

Defining abstract methods:

  • @abstractmethod: method subclass must implement
  • Abstract methods can have default implementation (subclass can call super())
  • Subclass can't be instantiated until all abstract methods are defined

Abstract properties:

  • @property @abstractmethod: property subclass must implement
  • Order matters: @property goes inside, @abstractmethod outside

Abstract class methods and static methods:

  • @classmethod @abstractmethod: class method subclass must implement
  • @staticmethod @abstractmethod: static method subclass must implement

Concrete methods in ABC:

  • Abstract classes can have concrete methods
  • Subclass inherits them; can override if needed
  • Useful for shared implementation, helper methods

Template method pattern:

  • ABC defines concrete method that calls abstract methods
  • Subclass implements abstract methods
  • Concrete method defines algorithm; abstract methods define steps

Multiple inheritance:

  • Class can inherit from multiple ABCs
  • Must implement all abstract methods from all ABCs
  • Python requires most derived ABC if multiple ABC hierarchies conflict

Structural subtyping (duck typing with ABCs):

  • @abstractmethod with only ... still requires override
  • But in real code, duck typing is more Pythonic than strict ABCs

isinstance() and ABCs:

  • isinstance(obj, ABC): check if instance
  • Can register virtual subclasses without inheritance:
    • ABC.register(MyClass) — MyClass considered subclass
    • isinstance(MyClass(), ABC) now returns True
    • No actual inheritance; just marks conformance

When to use:

  • Defining plugin interfaces
  • Enforcing team conventions across large codebase
  • Documenting expected methods in subclasses
  • Type checking with mypy/type hints

When duck typing is better:

  • Simple scripts where flexibility matters
  • Code that just needs “quacks like a duck” behavior
  • When multiple inheritance paths are complex
python-abc.md · Last modified: by 127.0.0.1