Operating context · Python
Model stock items and movements so invalid states are caught at clear boundaries and functions explain their contracts.
Start with the business or technical outcome
A small inventory program needs item records, positive quantities, movement types and a reliable way to compute available stock. The useful way to learn this process is to see its trigger, hand-offs, controls and close condition. Type hints improve communication and tooling, but they do not enforce business rules automatically at runtime.
Keep the domain small. Use Decimal for money when the exercise requires exact decimal arithmetic, and decide how units are represented. Avoid building a general ERP in one file.
Dataclasses reduce repetitive class code; they do not decide identity, mutation, validation or storage design. Those remain explicit choices.
What to understand before opening the tool
Understand annotations, built-in generic types, Optional or union types, dataclass fields, default factories, frozen instances, class versus instance data, post-initialization checks, protocols or typed dictionaries where appropriate, and static type checking.
Static analysis finds mismatched contracts before runtime, while tests verify behavior and runtime validation protects external inputs. These tools complement one another.
dataclasses
Use it for: define concise value-oriented records with generated methods Keep as evidence: readable domain classes
Type Annotations
Use it for: describe function inputs, outputs and collections Keep as evidence: static checker results
Runtime Validation
Use it for: reject invalid external values at construction or service boundary Keep as evidence: clear exceptions and tests
Unit Tests
Use it for: verify movement rules, defaults and edge cases Keep as evidence: repeatable behavior evidence
The process should finish with a typed Python domain model with dataclasses, validation, pure stock functions, serialization boundary and unit tests. Treat every hand-off as a possible control point. Note who supplies the input, who approves an exception and which report or record proves completion. This turns a memorised transaction into an operating procedure that another person could follow.
Run the process from trigger to close
Model valid states first, then create functions that transform them without hidden global data.
- Write domain examplesList valid and invalid items, movement types and stock outcomes.Checkpoint: Examples become test cases.
- Define value objectsCreate typed dataclasses with safe default factories and deliberate mutability.Checkpoint: Item and movement classes.
- Validate boundariesReject blank SKU, nonpositive quantity or invalid money input with specific messages.Checkpoint: Constructor or service tests.
- Implement pure calculationsCompute stock from movement sequences and return explicit results.Checkpoint: Typed function and tests.
- Add serializationConvert external dictionaries or JSON through a validation layer rather than unpacking blindly.Checkpoint: Round-trip and failure tests.
- Run static and dynamic checksUse a type checker plus unit tests and inspect one deliberately introduced mismatch.Checkpoint: Check reports and correction note.
A reliable operator knows where the process can pause without corrupting later work. Mark those points, define the owner and write the condition that allows work to continue.
Control points for reliable execution
Choose the Python construct according to the contract the data needs.
| Decision or signal | Action to take | Evidence to retain |
|---|---|---|
| dataclass | Domain record with behavior and generated representation | Instance tests and invariants |
| TypedDict | Typed shape for dictionary-like boundary data | Static checks at mapping use |
| NamedTuple | Light immutable tuple-compatible record | Simple value tests |
| Protocol | Structural behavior contract across implementations | Static substitutability check |
| Plain class | Full control over initialization and behavior | Explicit methods and tests |
Exceptions an operator must be ready to handle
Annotations can create false confidence if untrusted runtime input bypasses validation.
- Using a mutable list as a shared default: Use default_factory so instances do not share one list.
- Assuming hints reject bad input: Python normally does not enforce annotations by itself.
- Making every class frozen: Immutability should follow domain needs, not fashion.
- Mixing parsing with core calculations: Keep external-format errors at the boundary.
- Using float for exact currency casually: Select an appropriate numeric representation and rounding policy.
Turn the exercise into credible portfolio evidence
Publish a small package with models, services, boundary parsing and tests. Include a diagram showing external JSON becoming validated domain objects before calculation.
Add one type-checker error and explain what defect it prevented. Keep code and README proportional to the simple domain.
Explain it clearly in an interview
Explain what type hints do at runtime, why default_factory matters, where validation belongs and how dataclasses differ from a complete domain design.
Peer review before calling the work complete
Ask another learner to inspect the result without watching you build it. Give them the original scenario—a small inventory program needs item records, positive quantities, movement types and a reliable way to compute available stock.—and the evidence pack, but not your intended conclusion. They should be able to trace the input, identify the main decision and locate the proof of the output. If they cannot, improve the labels, timestamps or explanation instead of adding decorative screenshots.
Use this acceptance condition during the review: Static checks pass, invalid external values fail clearly, mutable defaults are safe, core calculations are deterministic and tests cover zero, duplicate and out-of-order cases. Record one question the reviewer raised and the change you made in response. That small feedback loop makes the Python type hints and dataclasses exercise more credible, easier to maintain and easier to explain under interview questioning.
Questions learners ask
Do Python type hints enforce types at runtime?
Normally no. They support readers and tools; runtime validation requires code or a validation library.
Why use default_factory?
It creates a fresh mutable default for each instance instead of sharing one object.
Should every data structure be a dataclass?
No. Choose according to behavior, identity, mutability and boundary needs.
Can a frozen dataclass never change?
It prevents normal field assignment through generated behavior, but deep immutability of contained objects requires separate design.
Use current product guidance
Menus, fields, permissions and service behavior can change between product versions or tenant configurations. Check the official Python documentation before applying version-sensitive steps in a live environment.
Build the complete skill path
Learn Python syntax, data structures, functions, OOP, files, databases, testing, debugging and automation by building small, explainable applications.
Final perspective
The real value of Python type hints and dataclasses is the ability to complete a controlled task and defend the result with evidence. A learner who can show the input, explain the decision, verify the output and describe one realistic exception demonstrates far more than someone who has only memorised a menu path or definition.