# 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. ```python # 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