Dependency injection means passing an object’s dependencies from the outside instead of constructing them internally. It makes code easier to test and change.

Constructor Injection

class RobotControls:
    def __init__(self, api):
        self.api = api
 
    def move_west(self):
        self.api.send_command('move_west', data={'meters': 1})

RobotControls depends on an object that has send_command. It does not need to know whether that object is a real API client, a mock, or a test double.

Benefit

The main benefit is substitutability. Tests can pass a fake dependency. Production code can pass the real dependency.

Cost

Constructor injection can create nested construction:

fence_guarding_robot = FenceGuardingRobot(RobotControls(RobotApi()))

When object graphs grow, dependency construction may need a factory or container.

Inheritance Is Not The Same

Using inheritance and super() can reduce constructor nesting, but it changes the relationship. Inheritance means “is a”; dependency injection means “uses a”.

This connects to Python Inheritance And Polymorphism because inheritance should preserve substitutability. When a class only needs to use another service, composition through dependency injection is often cleaner.

References