Skip to main content

Trace Tables: When Your Brain Takes Shortcuts

In Lesson 1, you practiced Predict-Run-Investigate on short code blocks where each variable was set once and never changed. Those predictions felt manageable; you could hold two or three values in your head and follow the logic to the output. Now the code gets longer, and something new happens: variables change.

Look at this code and predict the output before reading further:

count: int = 10
bonus: int = 5
count = count + bonus
bonus = bonus * 2
total: int = count + bonus
print(total)

If you predicted 20, you are in good company, and you are wrong. The correct answer is 25. Most beginners make this mistake because their brain uses a shortcut: it remembers the first value it saw for each variable and keeps using that value even after the code changes it. With two-line blocks, the shortcut works. With five-line blocks where variables update, it fails. This lesson gives you a tool that eliminates the shortcut entirely.


Why Your Brain Takes Shortcuts

Your working memory can hold about four to seven items at once. When a code block is two lines long, you can track every variable without effort. But the moment code reaches five or six lines, and variables start changing, your brain quietly substitutes the value it remembers most easily. That is usually the first value it encountered.

This creates a specific, predictable error: using the original value of a variable after it has been reassigned. It is not a sign of poor intelligence. It is a sign that working memory has limits, and the code has exceeded them.

If this is your first time seeing a variable change

In Lesson 1, every variable was set once: price: float = 29.99 stayed 29.99 for the entire block. That might have given you the impression that variables are permanent labels. They are not. A variable is a name that points to a value, and you can point it at a different value at any time. The code count = count + bonus takes the current value of count, adds bonus, and stores the result back into count. The old value disappears.

Consider the opening example. Here is what the shortcut error looks like:

What Your Brain DoesResulting (Wrong) Calculation
Remembers count as 10Uses 10 in the final line
Remembers bonus as 5Uses 5 in the final line
Calculates total = 10 + 5Gets 15 (or 20 if they half-trace)

The actual values at the final line are count = 15 and bonus = 10, giving total = 25. The brain's shortcut skipped the two reassignment lines entirely.

The fix is not "try harder" or "be more careful." The fix is a tool that makes every value visible at every step.

If you got the opening example right

You may have traced it carefully in your head. That works now, but it becomes unreliable as code grows. Trace tables are like showing your work in math class. Even when you can do the arithmetic mentally, writing it down catches errors that confidence misses.


What Is a Trace Table?

A trace table is a grid that tracks every variable's value after every line of code executes. It has one column for each variable, one column for the line number, and one column for any output.

If you already debug in your head

You may be thinking "I can track variables without drawing a grid." Many experienced developers feel that way, and most of them have spent hours hunting a bug that a trace table would have caught in seconds. Mental tracing fails in predictable ways: you skip a reassignment, you confuse two variables with similar names, you carry a stale value forward. Trace tables catch exactly those failures. Think of them as spell-check for your mental model.

Here is a simple example. Given this code:

a: int = 3
b: int = 7
a = a + b
print(a)

The trace table looks like this:

LineabOutput
13--
237
3107
410710

How to read it: Each row shows the state of every variable after that line executes. On line 1, a becomes 3 and b does not exist yet (shown as --). On line 2, b becomes 7. On line 3, a is updated to a + b, which is 3 + 7 = 10. The key: you use the values from the previous row to calculate the new row. On line 4, print(a) outputs the current value of a, which is 10.

To run this yourself, paste the code into your SmartNotes main.py and run it:

$ uv run python main.py
10

The rule that makes trace tables work: Always look at the row above to find a variable's current value. Never go back to the first row.


Building Your First Trace Table

Let us trace the opening example step by step. Here is the code again:

count: int = 10
bonus: int = 5
count = count + bonus
bonus = bonus * 2
total: int = count + bonus
print(total)

Start with an empty table. The columns are: Line, count, bonus, total, Output.

Line 1: count: int = 10 count is assigned 10. No other variables exist yet.

LinecountbonustotalOutput
110----

Line 2: bonus: int = 5 bonus is assigned 5. count has not changed.

LinecountbonustotalOutput
110----
2105--

Line 3: count = count + bonus This is the first reassignment. Look at the row above: count is 10, bonus is 5. So count + bonus is 10 + 5 = 15. The variable count is now 15. The old value 10 is gone.

LinecountbonustotalOutput
110----
2105--
3155--

Line 4: bonus = bonus * 2 Look at the row above: bonus is 5. So bonus * 2 is 5 * 2 = 10. The variable bonus is now 10. The old value 5 is gone.

LinecountbonustotalOutput
110----
2105--
3155--
41510--

Line 5: total: int = count + bonus Look at the row above: count is 15, bonus is 10. So total = 15 + 10 = 25.

LinecountbonustotalOutput
110----
2105--
3155--
41510--
5151025

Line 6: print(total) Output the current value of total.

LinecountbonustotalOutput
110----
2105--
3155--
41510--
5151025
615102525

To verify, paste the code into main.py and run it:

$ uv run python main.py
25

Notice what the trace table reveals: count changed from 10 to 15 on line 3, and bonus changed from 5 to 10 on line 4. If you used the original values (10 + 5 = 15) or half-traced (10 + 10 = 20), the trace table shows exactly where your mental shortcut went wrong.

If you already work with spreadsheets

A trace table works like tracking formulas across spreadsheet rows. Each row is a snapshot of all your "cells" after one operation. If you can follow a spreadsheet formula that references other cells, you can build a trace table.


Practice: Three Trace Tables

Now it is your turn. For each code block below:

  1. Read the code carefully
  2. Build the trace table on paper or in a text file (draw the grid, fill it row by row)
  3. Predict the output from your completed trace table
  4. Run the code in your SmartNotes main.py:
$ uv run python main.py
  1. Investigate: if your prediction was wrong, find the row where your trace went off track

Block 1: Area vs. Perimeter

width: int = 8
height: int = 5
area: int = width * height
width = width + 2
perimeter: int = 2 * (width + height)
print(f"Area: {area}, Perimeter: {perimeter}")

Pause here. Build the trace table before reading on.

Trace Table:

LinewidthheightareaperimeterOutput
18------
285----
38540--
410540--
51054030
61054030Area: 40, Perimeter: 30

Run it to verify:

$ uv run python main.py
Area: 40, Perimeter: 30

Investigate: The key insight is that area was calculated on line 3, when width was still 8. So area is 8 * 5 = 40. Then width changed to 10 on line 4. But area does not update; it keeps the value it was given on line 3. The perimeter calculation on line 5 uses the new width of 10: 2 * (10 + 5) = 30.

The common wrong answer: Area: 40, Perimeter: 26. This happens if you use the old width of 8 for perimeter: 2 * (8 + 5) = 26. The trace table shows that by line 5, width is 10, not 8.


Block 2: Strings Do Not Update Retroactively

name: str = "smart"
version: str = "1"
app: str = name + "Notes v" + version
version = "2"
print(app)

Pause here. Build the trace table before reading on.

If you are new to how strings work

When Python runs app = name + "Notes v" + version, it grabs the current values of name and version, joins the pieces into one finished string, and stores that string in app. After that, app holds the completed text; it has no memory of which variables built it. Changing version later is like tearing a page out of a notebook after someone already photocopied it. The photocopy does not change.

Trace Table:

LinenameversionappOutput
1"smart"----
2"smart""1"--
3"smart""1""smartNotes v1"
4"smart""2""smartNotes v1"
5"smart""2""smartNotes v1"smartNotes v1

Run it to verify:

$ uv run python main.py
smartNotes v1

Investigate: app was built on line 3 using the values at that moment: "smart" + "Notes v" + "1" produces "smartNotes v1". On line 4, version changes to "2", but app already holds the finished string "smartNotes v1". Reassigning version does not reach back and update app. The string was assembled once and is now independent of the variables that built it.

The common wrong answer: smartNotes v2. This happens when your brain assumes that changing version automatically changes anything that used version. It does not. In Python, app = name + "Notes v" + version evaluates the right side once, stores the result, and moves on. The result is a snapshot, not a live connection.


Block 3: AI-Generated Trace Challenge

This time, instead of reading a block from the book, you will ask Claude Code to generate one for you.

Open Claude Code in your SmartNotes project and paste this prompt:

Generate a 5-line Python code block using only variables with
type annotations, arithmetic, and print(). Include at least one
variable that changes value. Do NOT show the output.

Whatever code the AI generates, build a trace table for it on paper. Then paste the code into your SmartNotes main.py and run it:

$ uv run python main.py

Compare the actual output to your trace table prediction. If they do not match, look at the row where your trace went wrong.

Why AI-generated code?

Every student who reads this lesson gets the same Blocks 1 and 2. But Block 3 is different for everyone because the AI will generate a unique code block for you. This means you cannot look ahead for the answer. You must build the trace table yourself. This is also closer to real development: in practice, you trace code written by someone else (or generated by AI), not code you chose from a textbook.


The Rule

Every trace table in this lesson demonstrates one principle:

When a variable appears on the left side of =, it gets a new value. The old value is gone.

bonus: int = 5      # bonus is 5
bonus = bonus * 2 # bonus is now 10 -- the 5 is gone forever

This is variable reassignment. Python does not keep a history of old values. It replaces them. Once bonus becomes 10, there is no way to recover the 5 unless you stored it somewhere else.

If the stale-value error keeps tripping you up

A stale-value error means using a variable's first value after it has been reassigned to a new one, like using bonus = 5 on a line where bonus is actually 10. This is the single most common prediction error for beginners and it does not go away by "trying harder." The error happens because your brain is doing its job: it takes shortcuts to save effort. The fix is mechanical: draw the table, fill it row by row, and never calculate from memory. The table makes the error impossible because every value is written down.

When to use a trace table: Any time a code block has more than three lines and at least one variable that changes. If every variable is set once and never modified, you can trace in your head (like Lesson 1). The moment a variable appears on the left side of = for a second time, draw the table.


Exercises

Build trace tables for these code blocks on paper or in a text file. Predict the output from your table, then run the code to check.

Exercise 1: Running Total

total: int = 0
total = total + 10
total = total + 25
total = total + 5
print(f"Total: {total}")

Paste this into your main.py and run it after making your prediction:

$ uv run python main.py

Your trace table template:

LinetotalOutput
1
2
3
4
5

Exercise 2: Swap Attempt

a: int = 3
b: int = 7
a = b
b = a
print(f"a={a}, b={b}")

Your trace table template:

LineabOutput
1
2
3
4
5

Hint: The output may surprise you. Trace line 3 carefully: what value does a hold after that line? Then use that new value of a when tracing line 4.

Exercise 3: Temperature Conversion

temp_c: float = 100.0
temp_f: float = temp_c * 9 / 5 + 32
temp_c = 0.0
print(f"F: {temp_f}, C: {temp_c}")

Your trace table template:

Linetemp_ctemp_fOutput
1
2
3
4

This exercises the same principle as Block 2: does changing temp_c affect temp_f?


Try With AI

Open Claude Code and try these prompts to extend your trace table practice.

Prompt 1: Generate and Trace

Generate a 5-line Python code block that uses only variables
with type annotations (int, float, str), arithmetic operators,
and print(). Include at least one variable reassignment where
the variable's new value depends on its old value.
Do NOT show the output -- I will build a trace table to predict it.

After building your trace table and running the code:

Here is my trace table:
[paste your table]
My prediction was [your prediction]. The actual output was [actual].
Check my trace table row by row and tell me where I went wrong
(if anywhere).

What you're learning: You are using the AI as a practice partner that generates unlimited trace-table challenges. Each code block is different, so you cannot memorize answers; you must apply the method. Having the AI check your trace table row by row gives you immediate, specific feedback on exactly where your tracking went off.

Prompt 2: Common Mistake Diagnosis

Show me a 5-line Python code block using only variables with
type annotations, arithmetic, and print(). Then show TWO
predictions: one WRONG prediction that a beginner would make
by using the original variable values (the shortcut error),
and one CORRECT prediction from a proper trace table.
Explain why the wrong prediction happens.

What you're learning: You are seeing the shortcut error from the outside, watching someone else make the mistake instead of making it yourself. This builds your ability to spot stale-value errors in code reviews, which is exactly what Lesson 3 will ask you to do.

Prompt 3: Progressive Difficulty

Give me 3 Python code blocks to trace, each getting progressively
harder: the first has 3 lines, the second has 5, the third has 7.
Use only variables with type annotations, arithmetic, string
operations, and print(). Each block must have at least one variable
reassignment. Do NOT show the output.

What you're learning: Progressive difficulty builds your tracing stamina. Starting easy and increasing complexity mirrors how real code review works. By the time you finish the 7-line block, you will have proven that your trace table method scales beyond the examples in this lesson.


PRIMM-AI+ Practice: Trace Tables

Predict [AI-FREE]

Ask Claude Code to generate a trace challenge:

Generate a 5-line Python code block using only variables with
type annotations (int, float, str), arithmetic operators,
and print(). Include at least one variable reassignment where
the variable's new value depends on its old value.
Do NOT show the output.

Build a trace table on paper or in a text file (this is your mandatory trace artifact for this exercise). Predict the output from your completed table and record a confidence score from 1-5.

Run

Paste the code into main.py and run uv run python main.py. Compare to your trace table prediction and record the result: prediction, confidence, actual output. If they match, your tracing is accurate. If not, the next step tells you exactly where you went wrong.

Investigate

Paste your trace table to Claude Code and ask for a row-by-row check:

Here is my trace table: [paste it]
My prediction was [your prediction]. The actual output was [actual].
Check my trace table row by row and tell me where I went wrong.

The AI will identify the exact row where your trace diverged from reality. That row is where the stale-value shortcut caught you. Note that the trace table itself (the artifact you produced before asking the AI) is what makes this investigation possible. Without it, you would have nothing to compare against.

Error Taxonomy: If your trace was wrong, classify the error. Did you use the original value instead of the updated one (stale-value error, a type of logic error)? Did you confuse which variable was being reassigned (variable-tracking error, where you lose track of which name is changing)? Naming it makes the pattern visible.

Parsons Problem: Reconstruct the Execution Order

Here are the lines of a Python code block in scrambled order. Reconstruct the correct sequence so that print(total) outputs 25:

total: int = count + bonus
count = count + bonus
bonus = bonus * 2
print(total)
bonus: int = 5
count: int = 10

Arrange these six lines in the correct order. Then build a trace table for your reconstructed code and predict the output. Write your answer and a confidence score before checking.

Hint: Variables must be created before they can be used. And remember: when a variable is reassigned, later lines see the new value, not the old one. Build a trace table for your arrangement to verify it produces 25.

Modify

Take the code block the AI generated in the Predict step and add one more reassignment. Before running, extend your trace table with the new rows. Predict the output. Run and compare. Each modification makes the trace longer and tests whether your method scales.

Make [Mastery Gate]

Ask Claude Code for progressive difficulty:

Give me 3 Python code blocks to trace, each getting progressively
harder: 3 lines, 5 lines, 7 lines. Each must have at least one
variable reassignment. Do NOT show the output.

Build trace tables for all three, with confidence scores. Run all three. The 7-line block will test whether your trace table method holds under real complexity, the same complexity you will encounter when reviewing AI-generated code in future chapters. Getting all three trace tables correct is your mastery gate for this lesson. Track your confidence calibration: are your scores getting more accurate as you practice?


Common Beginner Mistakes With Trace Tables
  • Forgetting that variables update in place: When you see count = count + 1, the old value of count is gone. Your trace table should show the new value, not both.
  • Misreading indentation as decoration: In Python, indentation defines structure. A line indented under an if only runs when the condition is true. Indentation is logic, not formatting.
  • Skipping rows in the trace table: Every assignment changes state. If you skip a line, your predictions for later lines will be wrong. Trace every line, even the ones that look obvious.

James puts down his pen. The trace table for Block 3 is still on his desk, every row filled in, every variable tracked.

"You know what this reminds me of?" he says. "Reconciling a bank statement. You do not just check the final balance. You go line by line, matching every transaction against the ledger. If you skip a line, the totals drift and you spend hours finding the mismatch."

Emma tilts her head. "That is actually a useful way to think about it. The trace table is the ledger. Each row is a transaction." She hesitates, then smiles. "I had not thought of it in those terms before. The bank reconciliation framing might be clearer than the spell-check analogy I usually use."

"The stale-value error is the same problem," James continues. "If an accountant uses last month's balance instead of this month's, every number downstream is wrong. Same thing when your brain grabs the first value it saw instead of the updated one."

"Exactly. And the fix is the same in both cases: write it down. Do not trust memory." Emma taps the trace table. "You now have two tools. PRIMM for approaching any code block, and trace tables for tracking variables when they change. In Lesson 3, you combine both on a real piece of SmartNotes code. Longer code. Multiple variables changing. And somewhere in it, a bug."

James raises an eyebrow. "A bug I have to find by reading?"

"A bug your trace table will catch that your eyes alone would miss."