Reading — step 1 of 4
Learn
Putting It All Together
You've learned classes, dunder methods, generators, decorators, regex, and JSON as separate tools. Real programs are where they meet. The most common shape for a real program is the command loop: read a command, parse it, dispatch to the right handler, mutate some state, print a result. That's what a shell is, what a database CLI is, and what this lesson's inventory manager is.
The architecture
Three layers, cleanly separated:
- State + rules — a class that owns the data and enforces the invariants (chapter 1).
- Dispatch — mapping command names to handlers instead of growing an
if/elifladder forever. - The I/O loop — reading stdin until EOF and printing exact output.
Look closely at remove: it checks both failure cases before touching the data. Validate first, mutate last — a failed remove must leave the quantity exactly as it was. Guarding invariants like this is the whole reason the state lives inside a class instead of a bare dict scattered through the script.
Reading commands until EOF
for line in sys.stdin is the EOF-safe idiom — the loop simply ends when input ends. A while True: input() loop raises EOFError at the end and needs a try/except to avoid crashing after the last command.
If the if/elif ladder bothers you, dispatch through a dict — functions are first-class values:
Exact output is the contract
Graders — and every real program that consumes your output — compare text byte-for-byte. error: not found is not Error: Not Found. apple: 5 has a colon and a space. An empty inventory prints the single word empty, not nothing. When output is a protocol, formatting is correctness.
Where do the other tools fit? A production version of this program would persist self.items with json.dump on exit and json.load on startup, validate item names with a regex, and wrap each handler in a logging decorator. The architecture wouldn't change — that is the payoff of separating state, dispatch, and I/O.
Your exercise
Implement add, remove, search, and list exactly as specified. The mistakes the grader will catch: (1) remove on an item that was never added must print error: not found — the visible test issues a remove before any add, so unguarded self.items[name] access crashes; (2) a remove larger than the stock must print error: insufficient and leave the count unchanged — the hidden test runs add apple 3, remove apple 5, then expects search apple to print 3; (3) list on an empty inventory must print empty; (4) list lines are alphabetically sorted and formatted name: quantity with a colon and a space.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…