Debugging locates, diagnoses, and corrects defects in a program. It becomes essential when code is close to correct but fails a test or behaves unexpectedly, including code generated with Copilot. section 1.6 section 8.0
A practical debugging workflow is iterative:
- Test the function, including boundary and edge cases, and identify behavior that differs from expectations. section 1.6 section 8.5
- Read the code, revise the prompt, or ask Copilot for a fix when the cause is already apparent. section 8.2 section 1.4
- Add print statements to compare actual intermediate values with expected values until the mismatch reveals the bug. section 8.2.1
- Use VS Code breakpoints, stepping, variable inspection, and watch expressions when printed output is insufficient. section 8.2.2
- Retest after the fix; if the function remains difficult to debug, decompose it into smaller functions. section 8.4 section 8.7
Tracing an incorrect word counter
Suppose count_words should count only the exact word "Dan", but its condition uses substring matching. With ["Dan", "danger", "Leo"], it returns 2. Printing each counted word exposes "danger" as the unwanted match; the condition can then be changed to word == "Dan" and tested again. section 8.2.1
Listing 8.1 Incorrect function for counting matching words
def count_words(words):
count = 0
for word in words:
if "dan" in word.lower(): #1
count += 1
return count
Inspect the incorrect count_words function whose substring condition creates the debugging problem. section 8.2.1















