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.
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}")
Defining abstract methods:
@abstractmethod: method subclass must implementsuper())Abstract properties:
@property @abstractmethod: property subclass must implement@property goes inside, @abstractmethod outsideAbstract class methods and static methods:
@classmethod @abstractmethod: class method subclass must implement@staticmethod @abstractmethod: static method subclass must implementConcrete methods in ABC:
Template method pattern:
Multiple inheritance:
Structural subtyping (duck typing with ABCs):
@abstractmethod with only ... still requires override
isinstance() and ABCs:
isinstance(obj, ABC): check if instanceABC.register(MyClass) — MyClass considered subclassisinstance(MyClass(), ABC) now returns TrueWhen to use:
When duck typing is better: