Exercise 1: A Missing zip_code Key vs. a Missing Middle Positional Argument — Possible Solution ==================================================================== THE MORE REVEALING TEST: OMITTING city, NOT THE LAST FIELD ------------------------------ Testing with the last field missing (country) turns out to be too easy for both versions - both correctly name the actual missing field. The genuinely revealing test is omitting a MIDDLE field (city), since Python's own positional-argument filling can only ever report the LAST unfilled parameter, regardless of which one was actually skipped. BAD - OMITTING city, 8 POSITIONAL ARGS PASSED ------------------------------ create_user_bad('Jane', 'Doe', 'j@x.com', '555', '123 Main St', 'TX', '78701', 'USA') raised: create_user_bad() missing 1 required positional argument: 'country' Python fills parameters left to right - with city skipped, every argument after it (state, zip_code, country) silently shifts one position early ('TX' lands in state's own slot, '78701' in zip_code's, 'USA' in country's), leaving the actual LAST parameter (country) unfilled. The error message is genuinely misleading: it blames 'country', but city is the field that was actually omitted. GOOD - THE IDENTICAL MISTAKE, city KEY MISSING FROM THE BUNDLED DICT ------------------------------ address_missing_city = {'street': ..., 'state': 'TX', 'zip_code': '78701', 'country': 'USA'} raised: KeyError 'city' Because create_user_good explicitly accesses address['city'] by name (not by position), the error correctly and precisely names 'city' - the exact field that's actually missing, not some unrelated field that merely happened to run out of values first. WHY THIS IS A STRONGER FINDING THAN THIS CHAPTER'S OWN ORIGINAL TEST ------------------------------ This chapter's own original missing-argument test (omitting the LAST field) happened to produce a correctly-named error in both versions, which understates the real difference. Testing a MIDDLE omission reveals the genuine asymmetry: the bad version's error message actively misleads a developer toward the wrong field, while the good version's message is accurate regardless of WHICH field was actually left out - because keyword/dict-based access ties the error directly to the name being looked up, not to an arbitrary position in a sequence. WHY THIS WORKS AS AN ANSWER ------------------------------ A middle field, rather than the last one, is deliberately omitted to expose Python's own positional-filling behavior, both resulting errors are captured and compared directly, and the finding (a misleading error vs. an accurate one) is a stronger, more honest result than the chapter's own original test happened to show.