Python composition and object relationships
Build behavior by containing another object.
Python
class Engine:
def start(self):
return "Engine ready"
class Car:
def __init__(self, engine):
self.engine = engine
def start(self):
return self.engine.start() + "; car ready"
car = Car(Engine())
print(car.start())Output
Engine ready; car ready
Explanation
Composition models a has-a relationship. A Car delegates starting to its Engine instead of inheriting from Engine.
Passing the dependency into the constructor makes the relationship explicit and allows a different compatible engine to be supplied later.
Explore the dry run
Guided walkthroughReady
1
class Engine:2
def start(self):3
return "Engine ready"4
5
class Car:6
def __init__(self, engine):7
self.engine = engine8
def start(self):9
return self.engine.start() + "; car ready"10
11
car = Car(Engine())12
print(car.start())Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Create an Engine and pass it into Car. | car.engine = Engine instance | — | |
| Delegate to the contained engine. | car.engine = Engine instance | — | |
| Engine supplies its result. | engine result = Engine ready | — | |
| Combine and print the result. | engine result = Engine ready | Engine ready; car ready |
Cost and common mistakes
O(1) calls for this fixed object relationship.
- Car is not a kind of Engine; inheritance would misrepresent this relationship.
- Sharing a mutable dependency means multiple owners can observe its changes.
Try it yourself
Replace Engine with a compatible ElectricMotor returning Motor ready.
Reveal answer and reasoning
Pass ElectricMotor() to Car. The result is Motor ready; car ready without changing Car.