Debugging Techniques for Variable State
Variable updates are not special operations; they follow the same evaluation rules as all assignments: Python evaluates the right side first, then stores the result in the variable on the left.
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…
The Hidden Order of an Update
An assignment such as count = count + 1 can look as if Python changes count while it is still calculating the expression. That is not what happens. Python first evaluates the entire right-hand side, using the current value of count. Only after that calculation does it store the result in count. This evaluation order is the key to debugging variable state.
What do you think happens?
When Python processes count = count + 1, which happens first?
Reveal answer
Python looks up count and evaluates count + 1.
The right side is evaluated first. The resulting value is then stored in the variable on the left.
Tracing the Current Value
To debug an update, separate it into three actions. First, look up the variable's current value. Second, perform the arithmetic on the right side. Third, store the result in the variable on the left. For an increment, the arithmetic adds 1. For a decrement, it subtracts 1. The variable therefore moves from one state to the next rather than changing mysteriously.
Following an Increment
Suppose score has already been initialized with the value 4. Trace the update score = score + 1.
- 1Look up
Python finds the current value of score: 4.
- 2Calculate
Python evaluates the right side using that value: 4 + 1 produces 5.
- 3Store
Python stores the result, 5, in score.
score now has the value 5.
Initialization Before Change
Initialization means giving a variable an initial value before trying to update it. An update depends on reading the variable's current value, so the variable must already exist. If Python cannot find the variable while evaluating the right side, it raises a NameError.
Why the Starting Value Matters
Compare an update to a variable that has an initial value with an update to a variable that has not been initialized.
- 1Initialized case
If total has an initial value, Python can look up total, perform the arithmetic on the right side, and store the result.
- 2Uninitialized case
If total does not already exist, Python cannot obtain the current value needed to evaluate total + 1.
- 3Debugging conclusion
Check whether the variable was initialized before investigating the arithmetic in its update.
Initialization is required because an update reads the variable's current value.
Increment and Decrement
| Operation | Pattern | Effect on current value |
|---|---|---|
| Increment | x = x + 1 | Adds 1 |
| Decrement | x = x - 1 | Subtracts 1 |
Both patterns require x to have an existing value before the update.
Incrementing and decrementing use the same evaluation process. The difference is the arithmetic performed after the current value is read. An increment adds 1 to the current value. A decrement subtracts 1. In both cases, the result replaces the previous value stored in the variable.
Tracing Two Directional Updates
A variable begins with the value 7. Trace one increment followed by one decrement.
- 1Initial state
The variable's current value is 7.
- 2Increment
The update reads 7, adds 1, and stores 8.
- 3Decrement
The next update reads 8, subtracts 1, and stores 7.
After the two updates, the variable is back at 7, but each update still followed its own read, calculate, and store sequence.
Mistakes in State Tracing
Common mistake Treating an update as a special operation that changes the variable before evaluating the expression.
What it looks likeReading count = count + 1 as if count becomes 1 before the addition.
Why it failsPython evaluates the right side first and stores that result afterward.
Do this insteadTrace the old value, perform the arithmetic, and then record the new value.
Common mistake Updating a variable before giving it an initial value.
What it looks likeTrying to evaluate x = x + 1 when x does not yet exist.
Why it failsPython cannot look up x to evaluate the right side, so it raises a
NameError.Do this insteadInitialize the variable before using its current value in an update.
Common mistake Confusing an increment with a decrement.
What it looks likeDescribing x = x - 1 as adding to x.
Why it failsThe minus operation subtracts 1 from the current value.
Do this insteadCheck the operator: plus 1 increments, while minus 1 decrements.
When debugging several assignments, write down the variable's value after each completed assignment. For every update, record the value read, the arithmetic performed, and the value stored. This makes it possible to identify the exact step where the state becomes incorrect.
Practice the Three-Step Trace
A variable begins with the value 3. Trace an increment followed by a decrement. For each update, write the value Python reads, the arithmetic it performs, and the value it stores.
Hints
- The increment reads the initial value and adds 1.
- The decrement reads the result of the increment and subtracts 1.
- Do not calculate the second update from the original value; use the variable's current state.
Practice Check
A variable begins with the value 3. What is its value after an increment and then a decrement?
- 1Increment
Read 3, add 1, and store 4.
- 2Decrement
Read 4, subtract 1, and store 3.
The final value is 3.
A Reliable Debugging Routine
- 1Initialize a variable before updating it so Python can find its current value.
- 2Read the right side of an assignment from left to right as an expression to be evaluated before storage occurs.
- 3Trace every update as three actions: look up the current value, perform the arithmetic, and store the result.
- 4An increment adds 1 to the current value, while a decrement subtracts 1.
- 5When a state becomes incorrect, inspect the value after each assignment to locate the first incorrect transition.
Key Takeaways
- A variable update is an ordinary assignment: Python evaluates the right side first and stores the result on the left.
- The variable must already be initialized because the update needs its current value.
- Debugging becomes clearer when each update is traced as read, calculate, and store.
- Incrementing adds 1, while decrementing subtracts 1.
- Recording the state after each assignment reveals where an incorrect value first appears.