Debugging
Debugging means finding why a program behaves differently from its intended behaviour, fixing the cause, and checking the fix.
Use a repeatable process
- State the expected behaviour for a small example.
- Run that example and record what actually happens.
- Read any error message, including its type, line number and traceback.
- Trace the relevant code or print intermediate values to locate the first incorrect step.
- Change one cause at a time.
- Run the original example again, then check nearby and boundary inputs.
An error can be reported where a bad value is used, even if the value became wrong earlier. Work backwards through the relevant calls and assignments.
Recognise the kind of problem
- Syntax error: Python cannot parse the code, such as a missing colon.
- Runtime error: code starts but fails on a particular operation, such as accessing a missing list index.
- Logic error: code runs but produces the wrong answer.
Do not catch every exception just to hide it. Handling an expected bad input is Data Validation; unexpected faults still need investigation.
Find a logic error
This function is intended to total all the values in a list:
def total_scores(scores):
total = 0
for score in scores:
total = total + score
return total
print(total_scores([3, 5, 2]))
Expected: 10. Actual: 3. A trace shows that return runs during the
first iteration, ending the whole call.
Move return outside the loop:
def total_scores(scores):
total = 0
for score in scores:
total = total + score
return total
print(total_scores([3, 5, 2]))
print(total_scores([]))
print(total_scores([7]))
The results are 10, 0 and 7. Rechecking the original failing
example and these boundaries gives evidence that the fix works.
Inspect a value without changing the calculation
Temporarily put print("score:", score, "total:", total) inside the loop
after the addition. This reveals what each iteration did. Remove temporary
prints before submitting work with an exact output requirement.
Your turn: fix the boundary
sum_up_to(limit) should return the sum of the integers from 1 through limit, including the limit. Assume limit is a positive integer. Fix the code, then check limits of 3 and 1.
def sum_up_to(limit):
total = 0
for number in range(1, limit):
total = total + number
return total
print(sum_up_to(3))
print(sum_up_to(1))
Expected output
6
1
Explain why changing the stop to limit + 1 fixes the cause.
Do not replace the calculation with the two expected answers.
See also: Tracing Code, The range() Function, Parameters & Return.
Practise this in the free Python course, where every exercise checks your code instantly.