Phase 01 — Production Python Engineering
Difficulty: ⭐⭐⭐☆☆ Estimated Time: 2 weeks (30–40 hours) Roles Supported: every later phase — this is the engineering substrate the JD calls "expert-level programming skills in Python … enabling you to build scalable, production-grade systems"
Why This Phase Exists
Senior ML engineers are distinguished less by knowing more ML than by writing ML code that survives: typed interfaces other teams can build against, tests that catch regressions before the on-call does, and profiling instincts that find the real bottleneck. Every artifact in phases 02–13 is production-shaped Python; this phase sets the bar and the idioms once, so the rest of the track can assume them.
The flagship lab is a typed data-contract library — the kind of component that sits at every pipeline boundary in a real ML platform (and the reason tools like pydantic and pandera exist). Building one teaches the protocol/generic/dataclass machinery, error-design discipline, and property-style testing in one artifact.
Concepts
- Static typing as API design:
Protocol(structural typing), generics (TypeVar, parameterized containers),dataclasses(frozen, slots),Enum, exhaustiveness - Error design: exception hierarchies vs result types; collect-don't-raise validation; error messages as UX
- Iterators/generators as pipeline primitives; itertools; laziness and its traps
- Concurrency truthfully: the GIL, threads (I/O-bound) vs processes (CPU-bound) vs asyncio (many-waiting); what each buys for ML workloads
- Testing discipline: pytest fixtures/parametrize, property-style tests, golden files, test doubles at boundaries
- Profiling: cProfile/py-spy reading, the measure-first ethic
- Packaging and reproducibility: pyproject, pinned deps, src layout
Labs
Lab 01 — Typed Data-Contract Library (flagship, implemented)
| Field | Value |
|---|---|
| Goal | Build contracts: declare a schema (fields, types, constraints) as code, validate records against it with aggregated error reporting, and compose schemas — the boundary-guard component of every ML pipeline |
| Concepts | Protocols, generics, frozen dataclasses, collect-don't-raise, custom rules, property-style testing |
| Steps | 1. Field / Schema model; 2. built-in rules (type, range, regex, enum, nullability); 3. ValidationReport aggregating all failures with paths; 4. custom-rule protocol; 5. schema composition (extend/subset) + record coercion; 6. property-style round-trip tests |
| How to Test | pytest test_lab.py — 14 tests: rule semantics, aggregation, paths, protocol extensibility, coercion round-trips |
| Talking Points | Why collect-don't-raise at data boundaries? Protocol vs ABC? Why frozen dataclasses for schema objects? |
| Resume Bullet | Built a typed data-contract validation library with aggregated error reporting and protocol-based extensibility, used as the boundary guard across a multi-stage ML pipeline |
→ Lab folder: lab-01-data-contracts/
Extension Project A — Concurrency Benchmark Harness (spec)
Measure the same workload (CPU-bound feature transform; I/O-bound URL fetch simulation) under threads / processes / asyncio; produce the table that demonstrates the GIL's consequences; write the one-page "which concurrency for which ML workload" memo.
Extension Project B — Profiling Kata (spec)
Take a deliberately slow data-prep script (pandas anti-patterns: row-wise apply, repeated concat, object dtypes); profile with cProfile + line-profiler; fix the top three; document each fix's mechanism and speedup. Target: 50×+ end-to-end.
Guides in This Phase
- WARMUP.md — the full zero-to-expert guide for every concept above
Deliverables Checklist
- Lab 01 implemented; all 14 tests pass
- Extension A table + memo (or equivalent from your own work)
- Extension B with before/after profiles saved