Has-a, injection, and functions as parts
Add a new engine class and a lambda discount rule, and use them without changing Car or apply_discount.
Composition builds an object out of other objects it holds (has-a), while inheritance says one class is a kind of another (is-a). Passing collaborators in through parameters, keeping each class to one job, and using a plain function or dataclass when a class is overkill produce code that is easy to test and change.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write a Logger class that takes a write function in __init__ and has info(text) that calls write("INFO: " + text). Create one that prints and one that collects into a list.
Write a Player that HAS a Weapon (given to __init__), with attack() returning the weapon's use(). Use two weapon classes.
Rewrite this class as a function: class Greeter: def __init__(self, g): self.g = g and def greet(self, name): return self.g + ", " + name. Keep the same behaviour using functools.partial (Topic 9.5: it fixes some arguments of a function in advance) or a plain function.
Explain it without notes
What is the difference between inheritance and composition, and how do you choose?
What is dependency injection, and how do you do it in Python?
Explain the single-responsibility and open/closed principles with a Python example.
When is a function or dataclass better than a class?
Expected output
car: engine running
car: silent motor running
car: fake started
engine running
177.0
180.0 150
['email:disk full', 'sms:disk full']