Syllabus Lesson 81 of 141 · Bugs that lie
Bugs that lie

The shared default

Why it matters Some bugs only appear on the second call. They pass every test that makes one object, then corrupt data in production, where nothing is ever made only once.

A checkout service builds orders. A tester reports this:

a = new_order("ann")
add_item(a, "pen")
b = new_order("bob")
b["items"]   # expected [], got ["pen"]

Python works out a default argument value once, when the function is defined. Every call that uses the default gets the same list. That is the famous cause, and it is a real one here. But ask the question from the first lesson: what is the smallest true sentence about why Bob's order is wrong? It is not "the default is a list". It is "the order holds a list that somebody else also holds".

Aliasing: two names, or two objects, pointing at the same mutable value, so a change through one is seen through the other.

Your turn

Fix new_order (keep add_item as it is). The rule: each order owns its own items list and meta dict. Changing an order must never change another order, the defaults, or a list or dict the caller passed in. When not given, items start empty and meta starts as {"source": "web"}. The hidden tests change items and meta on orders made with and without arguments, and check the caller's values afterwards.

Spotted a problem in this lesson? Report it · Ask about this lesson

This exercise opens soon

Finish the lesson before it and this one unlocks. The whole course is free, no account needed, and you can read this lesson right now.