Debugging Strategies
About 20 minutes
Why this matters
Programmers spend more time fixing code than writing it. The skill is not being lucky; it is a method. A good habit turns a mysterious failure into a short, boring search.
The idea
- Reproduce it. Find the smallest input that fails:
last_n([1, 2, 3], 0). - Read the message. The last line of a traceback names the error; the line above points at your code.
- Look at the values. Print what is really there, not what you think is there.
f"{total=}"prints both the name and the value:total = 7 print(f"{total=}") # total=7 - Shrink the problem. Cut code away (or add
printcalls halfway) until you know which half is wrong. - Check your assumptions.
assert len(items) > 0, "items is empty"stops the program right where an assumption breaks. - Explain it aloud (the “rubber duck”). Saying what each line does often shows where it does not.
Most bugs are one of a handful of kinds: off-by-one, an edge case (empty, zero, one item, capitals), the wrong variable, or changing a list while looping over it.
Try it
Predict what last_n([1, 2, 3, 4], 2) returns, then run it with a print inside. Then try n = 0.
Your turn
The starter contains four functions. Each one has a bug. Fix all four without changing what they are supposed to do:
average(numbers): the mean of a list of numbers.count_vowels(text): how many vowels (a e i o u, either case) are in the text.last_n(items, n): the lastnitems as a new list ([]whennis 0 or less; the whole list ifnis bigger than its length).remove_negatives(numbers): a list without the negative numbers.
The test names and messages tell you what input failed. Reproduce, look, fix.
Recap
- Reproduce with the smallest failing input, then look at real values.
- Use
print/f"{x=}"andassertto check your assumptions. - Suspect edge cases and lists being changed while you loop over them.
Common mistakes
- Changing several things at once. Change one thing, run again.
- Trusting the code instead of the output. Print it.
- Fixing the symptom (special-casing one input) instead of the cause.