Debugging Techniques for Control Flow
While loops check their condition before each iteration; a boolean flag controls when the loop exits.
Try it: Debug by Tracing Execution
How to debug a program that runs but gives the wrong answer: compare expected and actual output, trace the lines in the order they really run with a variable watch table (or an inserted debug print), find the first line where a value goes wrong, then choose a fix and re-run to check it.
How it works
- State the expected output from the specification, run the program and compare: a difference is the evidence you debug from.
- Trace in execution order, not file order: loops repeat lines, if/elif picks one branch, and the watch table records every variable before each line runs.
- An inserted print('debug: ...', value) shows the same state in the output; it must not change what the program itself prints.
- Look for the first place a value differs from what it should be (an off-by-one range, > instead of >=, a total reset inside the loop, two names for one list, a str from input()). Where the wrong value shows up is only the symptom.
- Change one thing with a reason, re-run, and compare again: a fix that makes an error disappear can still leave the output wrong.
Default run (14 steps): Sum 1..n: Add up the whole numbers from 1 to n (n included) and print the sum. Press Play to trace it line by line. … Finished, but the output is wrong: got sum of 1 to 5 is 10, expected sum of 1 to 5 is 15.
Simplified: The lab's own small Python interpreter runs fixed, hand-written programs (you pick the program, the fix and a value; your text is never executed). Every program the lab can show was run in CPython 3.12 and the lab reproduces its output, its traceback text and its line-by-line trace. Six short programs, one editable value each; input() receives the value you type in the lab. Lines starting with "debug:" are ignored when comparing the output with the expected output.
Loading the simulation…
Close the Gap Between Intention and Execution
When a loop prints unexpected output or appears to run forever, the important question is not only what you intended the loop to do. You must determine what actually happened at each condition check, variable update, iteration, and branch. Loop tracing means following that exact sequence of state changes. Recording variable states step by step is the most reliable way to find where execution diverged from your mental picture.
Debug a loop as a sequence of states, not as one large block of code. At each step, ask what the condition is, what the variables contain, and which statement runs next.
Flag Checks Before Each Iteration
A while loop checks its condition before every iteration. When a boolean variable acts as a flag, the loop continues while that flag is True. The loop body can change the flag to False. That change does not erase the current iteration; it affects the next condition check. After the body finishes, the loop checks the flag again. If the flag is now False, the loop exits instead of starting another iteration.
Tracing a Flag-Controlled Loop
Suppose a loop starts with running equal to True and number equal to 1. During each loop body, number is processed. When number reaches 3, the body changes running to False. Trace the condition checks and state changes.
- 1Initial check
running is True, so the while loop begins its first iteration with number equal to 1.
- 2First body execution
The body processes number 1. The flag is not yet changed to False, so the next condition check still permits another iteration.
- 3Second body execution
The body processes number 2. The loop continues to the next condition check.
- 4Third body execution
The body processes number 3 and changes running to False.
- 5Final check
The body has finished, so the while condition is checked again. running is now False, so no fourth iteration begins.
The flag change ends the loop at the next condition check. It does not prevent the body that changed the flag from finishing.
Find the First Divergence
A useful debugging trace records the state before a condition check, the result of that check, the action taken in the loop body, and the state after the body. Compare this actual trace with your expected trace one step at a time. The first mismatch is the most useful location to investigate. Later unexpected behavior may simply be a consequence of that earlier mismatch.
- 1Write down the initial values of the loop variables and boolean flag.
- 2Record the condition before the first iteration.
- 3Record which branch or loop body runs.
- 4Write down every variable update made by that body.
- 5Check the condition again using the updated values.
- 6Compare the actual sequence with the sequence you expected and mark the first difference.
Natural Completion and Early Exit
A for loop iterates over the values in a sequence. Python also allows a for loop to have an else clause. The else block runs when the loop has gone through all of its iterations naturally. If a break statement exits the loop early, the else block is skipped. Therefore, reaching the end of the loop body repeatedly is different from leaving the loop through break.
Predicting the Else Clause
A for loop processes the values generated by range(1, 5). It prints each value, and its else block prints a completion message. Predict the order of events.
- 1Sequence creation
range(1, 5)generates 1, 2, 3, and 4. The upper boundary 5 is not included. - 2Iteration
The loop processes and prints 1, then 2, then 3, then 4.
- 3Completion decision
All values have been processed and no break has exited the loop.
- 4Else execution
Because the loop completed naturally, control moves to the else block.
The values 1, 2, 3, and 4 are processed first, followed by the else block.
Mistakes That Distort a Trace
Common mistake Treating a while condition as if it were checked only once
What it looks likeExpecting the loop to stop immediately when the flag changes inside the body
Why it failsThe current body execution continues. The changed flag is used at the next condition check.
Do this insteadRecord the state after the body, then trace the next condition check explicitly.
Common mistake Assuming the for loop else block always runs
What it looks likeExpecting else to run even after a break statement
Why it failsThe else block runs only after natural completion, not after break exits early.
Do this insteadMark whether the loop exhausted its values or left through break.
Common mistake Misreading range boundaries
What it looks likeExpecting range(1, 5) to include 5Why it failsThe source example specifies that
range(1, 5)generates integers from 1 up to but not including 5.Do this insteadWrite out the generated values before tracing the loop body.
Common mistake Skipping variable states between iterations
What it looks likeRecording only the final value instead of each update
Why it failsThe first unexpected result may arise earlier, during a condition check or update.
Do this insteadRecord the relevant variables before and after every loop body execution.
| Loop ending | What happened | Does for else run? |
|---|---|---|
| Natural completion | All loop iterations finished without break | Yes |
| break termination | break exited the loop before all iterations finished | No |
| while flag becomes False | The next condition check prevents another iteration | Not applicable to the for else rule |
Use the ending mechanism, not just the fact that the loop stopped, to predict the next control-flow step.
Trace Before You Change
A while loop begins with running equal to True and count equal to 0. Each iteration increases count by 1. When count becomes 2, the loop body changes running to False. Trace the initial condition check, every body execution, the value of count, and the final condition check. Then decide whether a third iteration begins.
Hints
- The condition is checked before the first iteration and again after each body execution.
- The body that changes running to False still completes.
- Use the updated value of running for the next condition check.
A for loop processes the values from range(1, 5). It contains a break that runs when the current value is 3, followed by an else clause. Predict which values are processed and whether the else clause runs. Explain your answer using the difference between natural completion and break termination.
Hints
range(1, 5)produces 1, 2, 3, and 4.- The break is reached while the value is 3.
- A loop that exits through break has not completed naturally.
A Reliable Trace Routine
- 1A while loop checks its condition before every iteration.
- 2A boolean flag can keep a while loop running until the loop body changes the flag to False.
- 3A for loop else clause runs after natural completion and is skipped when break exits early.
- 4
range(1, 5)includes 1, 2, 3, and 4, not 5. - 5The first difference between the expected trace and the actual trace is the best place to begin debugging.
Key Takeaways
- Trace loop execution by recording condition results, variable states, body actions, and the next control-flow step.
- A while loop checks its boolean condition before each iteration, so a flag changed inside the body affects the next check.
- A for loop with else runs the else block only when all iterations finish naturally.
- A break exits a for loop early and skips its else block.
- When debugging, locate the first point where actual execution differs from the expected trace.