Getting Started with Programming

Tracing, Debug Prints, and Reading Code Line by Line


Learning Objectives

  • You can distinguish between the program text and the changing program state.
  • You can trace a short program step by step and predict its output.
  • You can use debug prints to inspect what a program is doing while it runs.
  • You can write short comments that explain intent rather than restating the code.

So far, you have written programs and run them. This chapter is about the skill that connects writing to running: tracing. Tracing means following a program in your head, one line at a time, and keeping track of what changes. It is the single most important skill for reading code, debugging your own programs, and evaluating code that someone (or something) else has written.

Code Is Not the Same as State

When you look at a Python file, you see the code: the program text. When Python runs that code, variables appear, change, and disappear as execution proceeds. This changing set of values is the program state.

Take this short program:

name = input("Name: ")
greeting = f"Hello, {name}"
print(greeting)

The code is three lines. It stays the same every time you read it. The state changes depending on what the user types and which line has already run. Before the first line, there are no variables. After the first line, there is a variable name whose value depends on the user. After the second line, there is also a variable greeting. After the third line, the program has printed something and is about to end.

Learning to separate code from state is one of the most important early programming skills. It is what lets you say “I see why this line behaves like that” instead of “I have no idea, let me run it again and hope.”

Code and state

0 / 5 points

Which statement best describes the difference between code and program state?

Tracing a Short Program

To trace a program is to walk through it line by line and record what happens at each step.

When tracing, ask yourself, for each line:

  1. Which line runs first?
  2. What value does it produce?
  3. Which variable, if any, changes?
  4. What is printed?

Consider this example:

count = 2
count = count + 3
print(count)

A trace might look like this:

StepLineState after the lineOutput
1count = 2count = 2(nothing)
2count = count + 3count = 5(nothing)
3print(count)count = 55

That is a complete trace of a three-line program. It shows the state evolving from nothing, to count = 2, to count = 5, and the single line of output produced at the end.

The first time you trace a program this carefully, it feels slow. That is normal. With practice it becomes fast enough to do in your head for short programs.

Order the trace

0 / 5 points

The trace below shows what should happen when a short program runs. Arrange the code lines so that tracing your ordered program would produce this trace.

StepState after the lineOutput
1points = 3(nothing)
2points = 3, bonus = 5(nothing)
3points = 10, bonus = 5(nothing)
4points = 10, bonus = 510

A Slightly Longer Trace

Let’s trace a program that combines input, conversion, and arithmetic:

minutes_text = input("Minutes: ")
minutes = int(minutes_text)
hours = minutes / 60
print(f"That is {hours} hours.")

Suppose the user types 90.

StepLineState after the lineOutput
1minutes_text = input(...)minutes_text = "90"(the prompt is shown)
2minutes = int(minutes_text)minutes_text = "90", minutes = 90(nothing)
3hours = minutes / 60… plus hours = 1.5(nothing)
4print(f"That is {hours} hours.")unchangedThat is 1.5 hours.

A few things are worth noticing. After step 1, the value is the string "90", not the number 90. After step 2, both minutes_text and minutes exist — the conversion did not change minutes_text. After step 3, division produced a float, even though both operands could have been written as integers.

These are exactly the kinds of details that are easy to miss when reading a program quickly but obvious when you trace it slowly.

Complete a short trace

0 / 5 points

Trace this program:

pages = 8
bonus = 2
pages = bonus
bonus = 10

Arrange the state blocks in the order they happen. Use only the blocks that belong in the trace. Some blocks are distractors based on common tracing mistakes.

Debug Prints Make Invisible State Visible

Sometimes a program does not behave as expected, and tracing it in your head is not enough. A common reason is that your mental model of the state is wrong — you think a variable holds one thing, but it actually holds another.

A simple way to investigate is to add temporary print statements that show the state at specific points.

name = input("Name: ")
print("DEBUG: name is", repr(name))
greeting = f"Hello, {name}"
print("DEBUG: greeting is", repr(greeting))
print(greeting)

These extra print calls are usually called debug prints. They are not part of the program’s intended behavior. They exist to let you see inside it while it runs.

A small detail: repr(value) produces a representation that shows quotes around strings and makes whitespace visible. That is helpful when you suspect that the value is something slightly different from what you expected (for example, an empty string "" rather than None, or a value with a trailing space).

Debug prints are deliberately blunt. They are not pretty, and you remove them once the problem is solved. They are also one of the most reliable tools you have for understanding behavior, and they will keep being useful even in much more advanced programs.

Add a debug print

0 / 10 points

The program asks for a city and prints a short location note.

Add a temporary debug print after the input(...) line. The debug line should include the word DEBUG and show the value of city using repr(city).

Example input:

Oslo

The output should include a debug line like this, including the quotes and spaces around Oslo:

DEBUG: city is ' Oslo '

Comments Explain Intent, Not Every Line

A comment is text in the code that Python ignores when the program runs. In Python, comments start with #.

# Ask the user for a name and print a greeting.
name = input("Name: ")
print(f"Hello, {name}")

Comments are helpful when they explain intent, structure, or a non-obvious decision. They are not helpful when they restate what the code already says.

A bad comment:

# Set x to 5.
x = 5

A better comment:

# Start the score at five bonus points for new users.
score = 5

The first comment adds nothing. The second tells the reader why the value is 5, which is information you cannot get from reading the code alone.

A useful test: if you removed the comment, could a careful reader still figure out the same thing from the code itself? If yes, the comment is not pulling its weight.

Useful comments

0 / 5 points

Which comment is more useful?

Read, Predict, Run, Compare

The habit this chapter is really teaching is a four-step cycle:

  1. Read a short program carefully.
  2. Predict what it will do.
  3. Run it.
  4. Compare the actual result with your prediction.

If the result matches your prediction, your mental model is doing well. If it does not match, that is even more useful: the gap between what you expected and what happened is exactly where your understanding needs work.

When you start using AI assistants, this cycle is also how you check the code they generate. You will return to that idea in the next chapter.

Check Your Understanding

  1. In your own words, what is the difference between the code and the state of a running program?
  2. Trace the following program. What is its output, and what does each variable hold at the end?
a = 3
b = a + 2
a = b * 2
print(a)
print(b)
  1. When is a debug print more useful than just tracing the program in your head?
  2. Which of these two comments is more useful, and why?
# Increment count by 1.
count = count + 1
# Count this submission so the streak does not reset.
count = count + 1

AI Study Aid

Create a chapter diagram

We're looking into to what extent AI-generated diagrams could help with studying.

Use this study aid to generate an AI-generated visual summary of the material you just studied. Each diagram style emphasizes the content in a different way, so you can choose the focus that feels most useful.

Using the diagram generator is voluntary and does not affect your course progress. We encourage you to try it out and see if it helps, but it's totally up to you! Your answers help us understand how to make better study aids in the future.

Diagrams tried: 0