Mastering Dependency Inversion in Python with Abstract Base Classes
Overview of Dependency Inversion
Prerequisites
To follow this tutorial, you should understand
Key Libraries & Tools
- abc(Abstract Base Classes): A built-in Python module used to define blueprints for other classes. It ensures subclasses implement specific methods.
- Mypy: A static type checker that helps developers catch type-related errors before the code runs.
Code Walkthrough
1. Defining the Abstraction
First, we create an interface using the abc module. This defines what it means to be "switchable" without worrying about the device type.
from abc import ABC, abstractmethod
class Switchable(ABC):
@abstractmethod
def turn_on(self):
pass
@abstractmethod
def turn_off(self):
pass
2. Implementing the Subclasses
Now, we create a Switchable, making them compatible with any switch.
class LightBulb(Switchable):
def turn_on(self):
print("LightBulb: on")
def turn_off(self):
print("LightBulb: off")
class Fan(Switchable):
def turn_on(self):
print("Fan: spinning")
def turn_off(self):
print("Fan: stopped")
3. The Decoupled Power Switch
The Switchable.
class PowerSwitch:
def __init__(self, client: Switchable):
self.client = client
self.on = False
def press(self):
if self.on:
self.client.turn_off()
self.on = False
else:
self.client.turn_on()
self.on = True
Syntax Notes
The @abstractmethod decorator is a safeguard. If you inherit from ABC but forget to implement a decorated method, Python raises a TypeError the moment you try to instantiate the subclass. This enforces a strict contract between your components.
Tips & Gotchas
Always use type hints to signal your intent to other developers. While the Python interpreter ignores them, they are invaluable for documentation. A common mistake is trying to instantiate the abstract class itself; remember, Switchable is a blueprint, not a concrete object. Use this pattern whenever you find yourself writing code that is too tightly coupled to a specific implementation.

Fancy watching it?
Watch the full video and context