Final exercise. Six concepts in one tiny library:
Protocol HasArea describing the shape (area() -> float)@dataclass(slots=True) Square(side: float) with method area() returning side ** 2@dataclass(slots=True) Triangle(base: float, height: float) with method area() returning 0.5 * base * height@property total_area on a Catalog class containing a list of shapesenumerate_areas(shapes) yielding (index, area) pairsunittest.TestCase with parametrised casesThat's the whole track in 30 lines.
That's the point. Mastery doesn't add anything you couldn't have done with longer code in Patterns. It teaches the shapes — the six abstractions — that compose to make code shorter, clearer, more testable, more maintainable.
What would the same thing look like without these primitives?
Twice the code, no type information, no contract for new shapes, hand-rolled __init__ and __repr__ and __eq__ on every class, manual indexing instead of a generator, copy-pasted tests. Mastery isn't about what Python can do — Patterns gave you that. It's about how clean the code is when you're done.
| Primitive | From | Used for |
|---|---|---|
Protocol (structural typing) | L25 | HasArea describes the contract |
@dataclass(slots=True) | L5 + L26 | Square, Triangle — concise + memory-efficient |
| Type hints | L6 | every parameter and return |
@property | L23 | Catalog.total_area as a derived attribute |
Generator with yield | L11 | enumerate_areas lazy stream |
unittest + subTest | L17-L18 | parametrised tests |
from dataclasses import dataclass
from typing import Protocol, runtime_checkable
import unittest
@runtime_checkable
class HasArea(Protocol):
def area(self) -> float:
...
@dataclass
class Square:
side: float
def area(self) -> float:
return self.side ** 2
@dataclass
class Triangle:
base: float
height: float
def area(self) -> float:
return 0.5 * self.base * self.height
class Catalog:
def __init__(self, shapes):
self.shapes = shapes
@property
def total_area(self) -> float:
return sum(s.area() for s in self.shapes)
def enumerate_areas(shapes):
for i, s in enumerate(shapes):
yield (i, s.area())
class TestCatalog(unittest.TestCase):
def test_individual(self):
cases = [
(Square(5), 25),
(Triangle(3, 4), 6.0),
(Square(2), 4),
]
for shape, expected in cases:
with self.subTest(shape=type(shape).__name__):
self.assertEqual(shape.area(), expected)The dialog mentions @dataclass(slots=True) but the exercise's verification uses plain @dataclass to keep failure modes simple. In a real codebase with many shape instances, you'd add slots=True to both — same one-line change.
Given shapes = [Square(5), Triangle(3, 4)]:
Catalog(shapes).total_area returns 31.0 — @property + sum over area()list(enumerate_areas(shapes)) returns [(0, 25), (1, 6.0)] — generator yielding pairsisinstance(Square(5), HasArea) is True — structural checkSix concepts from across all four weeks. No new ideas; just careful arrangement.
Final exercise. Six concepts in one tiny library:
Protocol HasArea describing the shape (area() -> float)@dataclass(slots=True) Square(side: float) with method area() returning side ** 2@dataclass(slots=True) Triangle(base: float, height: float) with method area() returning 0.5 * base * height@property total_area on a Catalog class containing a list of shapesenumerate_areas(shapes) yielding (index, area) pairsunittest.TestCase with parametrised casesThat's the whole track in 30 lines.
That's the point. Mastery doesn't add anything you couldn't have done with longer code in Patterns. It teaches the shapes — the six abstractions — that compose to make code shorter, clearer, more testable, more maintainable.
What would the same thing look like without these primitives?
Twice the code, no type information, no contract for new shapes, hand-rolled __init__ and __repr__ and __eq__ on every class, manual indexing instead of a generator, copy-pasted tests. Mastery isn't about what Python can do — Patterns gave you that. It's about how clean the code is when you're done.
| Primitive | From | Used for |
|---|---|---|
Protocol (structural typing) | L25 | HasArea describes the contract |
@dataclass(slots=True) | L5 + L26 | Square, Triangle — concise + memory-efficient |
| Type hints | L6 | every parameter and return |
@property | L23 | Catalog.total_area as a derived attribute |
Generator with yield | L11 | enumerate_areas lazy stream |
unittest + subTest | L17-L18 | parametrised tests |
from dataclasses import dataclass
from typing import Protocol, runtime_checkable
import unittest
@runtime_checkable
class HasArea(Protocol):
def area(self) -> float:
...
@dataclass
class Square:
side: float
def area(self) -> float:
return self.side ** 2
@dataclass
class Triangle:
base: float
height: float
def area(self) -> float:
return 0.5 * self.base * self.height
class Catalog:
def __init__(self, shapes):
self.shapes = shapes
@property
def total_area(self) -> float:
return sum(s.area() for s in self.shapes)
def enumerate_areas(shapes):
for i, s in enumerate(shapes):
yield (i, s.area())
class TestCatalog(unittest.TestCase):
def test_individual(self):
cases = [
(Square(5), 25),
(Triangle(3, 4), 6.0),
(Square(2), 4),
]
for shape, expected in cases:
with self.subTest(shape=type(shape).__name__):
self.assertEqual(shape.area(), expected)The dialog mentions @dataclass(slots=True) but the exercise's verification uses plain @dataclass to keep failure modes simple. In a real codebase with many shape instances, you'd add slots=True to both — same one-line change.
Given shapes = [Square(5), Triangle(3, 4)]:
Catalog(shapes).total_area returns 31.0 — @property + sum over area()list(enumerate_areas(shapes)) returns [(0, 25), (1, 6.0)] — generator yielding pairsisinstance(Square(5), HasArea) is True — structural checkSix concepts from across all four weeks. No new ideas; just careful arrangement.
Create a free account to get started. Paid plans unlock all tracks.