The PRIMM Method -- Predict, Run, Investigate
In Chapter 44, you built the workbench: uv, pyright, ruff, pytest, and Git. Every tool is installed, every configuration file is in place, and SmartNotes has a clean foundation. Now you use it. This chapter is where you meet Python for the first time, not by writing it, but by reading it.
Before you see a single line of Python, you need to know the method you will use to read it. That method is called PRIMM, and it is the backbone of this entire course.
What Is PRIMM?
PRIMM (Predict, Run, Investigate, Modify, Make) was developed by computing education researchers Sue Sentance, Jane Waite, and Maria Kallia. It is built on an insight that decades of teaching have confirmed: novice programmers fail not because they cannot type code, but because they cannot read it. Students who jump straight to writing code produce syntax they do not understand, copy patterns they cannot adapt, and freeze when something breaks. PRIMM fixes this by reversing the order: you read before you write, you predict before you run, you understand before you produce.
The method is used in classrooms worldwide because it works. You do not start learning French by writing essays. You start by reading sentences, recognizing words, and building comprehension. PRIMM applies the same principle to code. It builds comprehension first, then builds on that comprehension to reach modification and creation.
Why PRIMM Matters in the AI Era
Before AI coding tools, the bottleneck in software development was writing code. Developers spent most of their time typing, debugging (finding and fixing errors in) syntax (the rules for how code must be written), and looking up documentation for libraries and services. Writing was slow, so reading was a secondary concern.
AI changed the equation. Tools like Claude Code and GitHub Copilot generate code in seconds. Writing is no longer the bottleneck. Verification is. GitClear's 2025 research, analyzing 211 million changed lines of code, found that 7.9% of newly added code was revised within two weeks in 2024, up from 5.5% in 2020 (a roughly 44% relative increase in code churn), meaning code that gets written and then quickly rewritten (calculated from the 5.5% and 7.9% figures). Code is being written faster but corrected more often. The bottleneck has moved.
| Era | Bottleneck | Primary Skill | What Slows You Down |
|---|---|---|---|
| Pre-AI | Writing code | Typing, syntax recall, API lookup | Producing code from scratch |
| AI era | Verifying code | Reading, predicting, tracing | Deciding whether generated code is correct |
PRIMM builds exactly the skills AI cannot replace. When a beginner asks Claude Code to write a function, they get correct code in seconds. They can run it and move on. But they have learned nothing. They cannot predict what the code will do if the input changes. They cannot debug it when it breaks. They cannot modify it when requirements shift. Four of PRIMM's five stages are about comprehension, reasoning, and adaptation; these happen inside your head, not inside an AI. PRIMM builds the developer's mental model (your brain's internal picture of how the code works). AI is the most powerful tool the developer will use.
The Five Stages
| Stage | What You Do | Why It Matters in the AI Era | This Chapter? |
|---|---|---|---|
| Predict | Read the code and predict its output before running it | Trains your mental compiler. Without it, you cannot evaluate whether AI-generated code is correct. | Yes |
| Run | Execute the code and compare the actual output to your prediction | Creates the feedback loop. The gap between your prediction and reality is where learning happens -- AI cannot experience this gap on your behalf. | Yes |
| Investigate | Explore why the code behaves the way it does -- especially when your prediction was wrong | Builds diagnostic instinct. Tracing variables, testing edge cases, asking "what happens if the input changes?" -- this is the work of a developer who can partner with AI rather than depend on it. | Yes |
| Modify | Change part of the code and predict what the change does | The most common real-world task in AI-assisted development. Developers spend far more time modifying AI suggestions than accepting them wholesale. | Next chapter |
| Make | Write new code from scratch using the patterns you have learned | In the AI era, "Make" means: write the specification, prompt Claude Code, then critically evaluate what it produces. The creative act is the culmination of understanding, not the starting point. | Next chapter |
This chapter focuses on the first three stages. They form a tight loop: predict, run, investigate. Each pass through the loop either confirms your understanding or reveals a gap. Both outcomes are useful. A correct prediction means your mental model works. A wrong prediction tells you exactly where your mental model needs updating.
Why prediction matters: When you predict before running, you commit to an answer. That commitment forces your brain to engage with the code rather than passively absorb it. If you skip prediction and just run the code, you see the output and think "oh, that makes sense," but you have no way to know whether you would have gotten it right on your own. Prediction turns reading into a test you give yourself.
PRIMM is not just this chapter. It is the method you will use throughout Part 4. Every new Python feature you encounter (functions, collections, classes, async patterns) will go through the same cycle: see it, predict it, run it, investigate it. By the time you reach Phase 5, PRIMM will be a reflex, not a step you consciously think about. The method does not change. The code gets more complex. Your reading skill grows with it.
That is exactly the right starting point for this chapter. You are not behind; you are in position. Every code block in this lesson is short (2-4 lines), uses plain English variable names, and has type annotations that tell you what kind of data each variable holds. You do not need to memorize anything. You need to predict, run, and compare.
Reading Is Not Scanning
There is a difference between looking at code and reading it. Looking is passive: your eyes move over the lines, you recognize some words, and you move on with a vague sense of what the code "probably" does. Reading is active. It requires your brain to do work.
Active reading has three components:
| Activity | What Your Brain Does | Example |
|---|---|---|
| Predicting | Guess the output before running the code | "This line adds two numbers, so the result should be 13" |
| Tracing | Follow each line in order, tracking what changes | "After line 1, x is 5. After line 2, y is 3. After line 3, result is 8." |
| Explaining | Put into words why the code produces its result | "The // operator divides and drops the decimal, so 10 // 3 gives 3, not 3.33" |
Scanning feels productive because it is fast. Active reading feels slow because it forces you to think. But scanning produces false confidence: you believe you understand the code when you do not. Active reading produces real understanding, one line at a time.
Reading Python: What You'll See
Every code block in this lesson uses the same four building blocks. Knowing what they are turns your predictions from random guesses into informed reasoning.
Variables are named containers. greeting = "Hello" stores the text Hello in a container called greeting. You choose the name; Python remembers the value.
Type annotations are the : str, : int, : float, : bool labels after variable names. They tell you what kind of data the variable holds, like labels on kitchen jars. They do not change what the code does. They make code easier to read.
| Type | What It Holds | Example |
|---|---|---|
str | Text (a "string") | "Hello", "3.14" |
int | Whole number | 7, -2, 0 |
float | Decimal number | 3.14, 0.5 |
bool | True or False | True, False |
print() displays whatever is inside the parentheses on your screen. Every block ends with print() so you can check your prediction against the actual output.
Expressions are pieces of code that produce a value. 3 + 5 is an expression (it produces 8). greeting + ", " + name is an expression (it produces a combined string). Any code on the right side of = is an expression being evaluated.
With these five pieces (variables, type annotations, types, print(), and expressions) you can read every block that follows.
Your First Four Predictions
Time to practice. For each block, you will ask Claude Code to generate a short Python snippet, read what it produces, predict the output, and then run the code. This mirrors real AI-driven development: the AI writes, you read and verify.
How to run each block: Paste the code into your SmartNotes main.py file (replacing any previous contents). Then open your terminal (the command window you set up in Chapter 44) and run:
$ uv run python main.py
The $ sign represents your terminal prompt. Do not type it. Type only the text after it: uv run python main.py.
uv is the package manager you installed in Chapter 44. uv run python main.py tells it to execute your Python file.
Block 1: String Concatenation
What's new here: When you use + between strings, Python joins them end to end. This is called concatenation, not addition. Characters inside quotes (including commas and spaces) appear exactly as written in the output.
Open Claude Code in your SmartNotes project and type this prompt:
Generate a 3-line Python snippet that creates two string variables
called greeting and name (with type annotations), joins them together
with a comma and space, and prints the result.
Read what the AI generates. A typical response looks like this:
greeting: str = "Hello"
name: str = "James"
message: str = greeting + ", " + name + "!"
print(message)
Pause here. Before you run it, predict: what will print(message) display? Write your prediction down or say it out loud. Then paste the code into main.py and run it.
$ uv run python main.py
Hello, James!
Investigate: The + operator joins strings end to end. greeting holds "Hello", then + attaches ", ", then name attaches "James", then + attaches "!". If your prediction matched, your mental model of string concatenation is working. If you predicted something like Hello James! (missing the comma and space), look again at the second piece: ", ". The comma and space are inside the quotes, so they are part of the string.
Notice what just happened: the AI generated the code, but you did the thinking. You read it, predicted the output, and checked whether your understanding was correct. That is the core loop of this chapter.
Block 2: Floor Division
What's new here: Python has two division operators. A single / gives the full decimal result (10 / 3 produces 3.3333...). A double // is floor division: it divides and drops everything after the decimal point, giving a whole number. Watch which operator the code uses.
Ask Claude Code:
Generate a 3-line Python snippet that divides 10 by 3 using floor
division (//), stores the result in a variable with a type annotation,
and prints it.
Read the generated code. It will look something like:
x: int = 10
y: int = 3
result: int = x // y
print(result)
Pause here. What will print(result) display? This one catches many people. Commit to your answer, then run it.
$ uv run python main.py
3
In Python, // always floors toward negative infinity, not toward zero. For positive numbers, this is the same as truncation. For negative numbers, -7 // 2 gives -4, not -3. This distinction matters when you encounter negative values later in the course.
Investigate: If you predicted 3.33 or 3.3333, you were thinking of regular division (/). Floor division (//) always rounds down to the nearest whole number. The AI generated code using // specifically. Part of reading code is noticing which operator was used; a single character changes the result entirely.
Block 3: F-Strings and Arithmetic
What's new here: An f before the opening quote makes an f-string (formatted string). Inside an f-string, anything between { and } gets replaced with that variable's value. Without the f, Python prints the literal text {total} instead of the number. Also note: multiplying a float by an int produces a float.
Ask Claude Code:
Generate a Python snippet that multiplies a float price (29.99) by an
integer quantity (3), stores the total, and prints it inside an
f-string that says "Total: $" followed by the total. Use type
annotations on all variables.
Read the response. A typical generation:
price: float = 29.99
quantity: int = 3
total: float = price * quantity
print(f"Total: ${total}")
Pause here. What will print(...) display? Predict the exact text.
$ uv run python main.py
Total: $89.97
Investigate: Three things happen in this block. First, price * quantity multiplies a float by an integer; Python handles this automatically, producing a float. Second, the f-string evaluates {total} and inserts the value. Third, the $ appears in the output as-is.
If you predicted Total: $89.97000000000001, your instinct about floating-point precision was technically sound. Python's float type sometimes produces tiny rounding artifacts. In this case, 29.99 * 3 happens to display as 89.97, but similar calculations can surprise you with extra decimals.
Block 4: Boolean Logic
What's new here: Comparisons like > (greater than) produce a boolean result: either True or False. The and operator combines two booleans and returns True only when both sides are True. If either side is False, the result is False.
Ask Claude Code:
Generate a Python snippet that sets a temperature variable to 35
(integer), checks if it is greater than 30, sets a humidity boolean
to True, combines them with "and", and prints the result. Use type
annotations on all variables.
Read the generated code:
temperature: int = 35
is_hot: bool = temperature > 30
is_humid: bool = True
feels_bad: bool = is_hot and is_humid
print(feels_bad)
Pause here. What will print(feels_bad) display?
$ uv run python main.py
True
Python capitalizes its boolean values: True and False, not true and false. If you predicted lowercase, that is a common expectation from JavaScript, Java, or C-family languages. Also, print() displays the word True, not the number 1, even though Python treats True as equivalent to 1 internally.
Investigate: Line by line: temperature > 30 asks "is 35 greater than 30?" The answer is True, so is_hot becomes True. is_humid is set directly to True. The and operator returns True only when both sides are True. Since both are True, feels_bad is True.
Why This Works
There is a reason PRIMM starts with reading, not writing. It mirrors how people learn languages. You do not start learning French by writing essays. You start by reading sentences, recognizing words, and building comprehension. Writing comes after you can read, because writing requires you to produce what reading only requires you to recognize.
In each prediction block, you followed the same cycle that professionals use when reviewing AI-generated code:
- SEE it: The AI generated a snippet
- READ it: You examined every line, checking variable names, types, and operators
- PREDICT it: You committed to what the output would be before running the code
Each prediction built a small piece of your mental model:
- Block 1 taught you that
+joins strings and that characters inside quotes (like,) appear exactly as written - Block 2 taught you that
//is not the same as/: floor division drops the decimal - Block 3 taught you that f-strings evaluate expressions inside
{}and that Python mixesfloatandintarithmetic automatically - Block 4 taught you that comparisons produce
TrueorFalseand thatandrequires both sides to beTrue
Wrong predictions are the most valuable part of this process. A correct prediction confirms what you already know. A wrong prediction reveals a specific gap (// vs /, True vs true, how f-strings work) that you can now fill. Every gap you fill makes the next prediction more accurate.
Exercises
Practice the Predict-Run-Investigate cycle on these new code blocks. Write your prediction before running the code.
Exercise 1: String Repetition
dash: str = "-"
line: str = dash * 20
label: str = "SmartNotes"
print(line)
print(label)
print(line)
Predict what three lines print() will display. Then paste into main.py and run:
$ uv run python main.py
Compare your prediction to the actual output.
Exercise 2: Floor Division Round-Trip
a: int = 17
b: int = 5
quotient: int = a // b
product: int = quotient * b
print(f"{a} // {b} = {quotient}, and {quotient} * {b} = {product}")
Predict the exact output string. Does multiplying quotient * b give back the original a? Why or why not?
$ uv run python main.py
Exercise 3: Boolean Combination
score: int = 72
passing: bool = score >= 70
excellent: bool = score >= 90
both: bool = passing and excellent
print(f"Passing: {passing}, Excellent: {excellent}, Both: {both}")
Predict all three boolean values. Remember: and returns True only when both sides are True.
$ uv run python main.py
Try With AI
Open Claude Code and try these prompts to extend your prediction practice.
Prompt 1: Generate and Explain
Generate a 3-line Python snippet that uses type annotations
for str, int, and float variables, then prints a result.
After showing the code, explain what each type annotation means
and why it matters for code readability.
What you're learning: You are seeing how the AI generates typed Python and whether its explanations match what you learned in this lesson. Compare its type annotation explanations with what you observed in the four code blocks above. If the AI uses a concept you have not seen yet (like a function or a list), ask it to simplify using only variables and print().
Prompt 2: Surprise Me
Generate a 3-line Python code block using only variables,
arithmetic operators, and print(). Make the output surprising --
something where the result is not what most beginners would
predict. Do NOT reveal the output. Let me predict first.
After predicting and running the code:
My prediction was [your prediction]. The actual output was
[actual output]. Explain why I got it [right/wrong].
What you're learning: You are practicing PRIMM with AI-generated code, the exact situation you will face when AI generates code in your projects. The AI creates the surprise; you practice the prediction. This is the core skill loop of this chapter applied to a new, unpredictable example.
Prompt 3: Quiz Me
Give me 5 short Python code blocks (2-3 lines each) that use
only variables with type annotations, arithmetic operators
(+, -, *, /, //), string operations (+, *, f-strings),
boolean logic (and, or, comparisons), and print().
Do NOT show the output. I will predict each one, then you
check my answers.
What you're learning: You are turning the AI into a practice partner that generates unlimited prediction exercises. This is more effective than re-reading the same four blocks because each quiz is different, forcing you to apply your mental model to new situations rather than memorizing specific answers.
PRIMM-AI+ Practice: Your First Predictions
Predict [AI-FREE]
Ask Claude Code to surprise you:
Generate a 3-line Python code block using only variables,
arithmetic operators, and print(). Make the output surprising,
something where the result is not what most beginners would predict.
Do NOT reveal the output.
Read the generated code. Write down your prediction and a confidence score from 1-5 (1 = total guess, 5 = completely certain). This is PRIMM-AI+ Rule 1 in action: never run code you have not predicted. The confidence score helps you track how well you know what you know.
Run
Paste the code into main.py and run uv run python main.py. Compare the output to your prediction. Record your result: prediction, confidence score, actual output. Were you right? If your confidence was high but your prediction was wrong, that mismatch is a calibration signal: it means you thought you understood something you did not. Note it.
Investigate
If your prediction was wrong, write a "why I got it wrong" note in your own words before asking the AI. This is your trace artifact, your understanding made visible before AI assistance.
Then ask Claude Code:
My prediction was [your prediction]. The actual output was
[actual output]. Explain why I got it wrong.
Compare the AI's explanation to your own note. But do not stop there. PRIMM-AI+ Rule 2 says never trust an explanation you have not tested. Verify the explanation by changing one value in the code and predicting the new output. Run it. Does the explanation hold?
Error Taxonomy (a system for classifying bugs into categories, introduced in Chapter 43): If your prediction was wrong, classify the error. Did you confuse string concatenation with addition (type error)? Did you misunderstand how // works (logic error)? Did you predict the right type of operation but get the value wrong (data/edge-case error)? Naming the error makes it easier to spot next time.
Modify
Take the code block the AI generated and change one variable. Before running the modified version, predict the new output. Then run it. This is the Modify stage at its simplest: one change, one prediction, one verification.
Make [Mastery Gate]
Ask Claude Code to quiz you:
Give me 5 short Python code blocks (2-3 lines each) using only
variables with type annotations, arithmetic, string operations,
boolean logic, and print(). Do NOT show the output.
Predict all five, with a confidence score for each. Run all five. Score yourself: how many did you get right? Track which confidence levels matched reality: are your 4s and 5s actually correct? Are your 2s and 3s actually uncertain? That calibration is the meta-skill PRIMM-AI+ builds. Getting 4 out of 5 correct with well-calibrated confidence scores is your mastery gate for this lesson.
You just predicted code output before running it. That predict-then-check habit is Rung 1 of the Verification Ladder, the rung every other rung depends on. In later chapters, you will add types (Rung 2), tests (Rung 3), pipelines (Rung 4), and observability (Rung 5). But it all starts here, with the commitment to predict before you run.
- Confusing
=with==: A single=assigns a value (x = 5means "store 5 in x"). A double==compares two values (x == 5means "is x equal to 5?"). When reading code, always check: is this storing or comparing? - Skipping the prediction step: Jumping straight to running code feels faster, but you learn less. The prediction is where your mental model gets built.
- Reading code like English, left to right: Python evaluates the right side of
=first, then stores the result on the left.total = price + taxmeans "calculate price + tax, then store it in total."
James leans back and stretches. Four prediction blocks. Two right, two wrong. The wrong ones taught him more.
"It is like auditing a supplier's invoice," he says. "You do not just glance at the total. You check every line item against the purchase order. If one line is off, you know exactly where the problem started."
Emma nods slowly. "That is closer to what professional developers do than most people realize." She pauses, then adds: "I am honestly not sure whether the predict-first habit sticks for everyone on the first session. Some of the research suggests it takes three or four rounds before the mental model starts to feel natural. I have seen students where it clicks immediately, and students where it takes a week."
James looks at his notes. "Four blocks. Four types: strings, floor division, f-strings, booleans. Each one built a small piece of the picture."
"And the wrong predictions built the biggest pieces," Emma says. "Correct predictions confirm what you know. Wrong predictions show you exactly where the gap is." She glances at his screen. "But these blocks were short. Two, three, four lines. What happens when the code gets longer and variables start changing?"
James frowns. "My brain will probably start taking shortcuts."
"It will. Lesson 2 gives you a tool for that: trace tables. They make every variable visible at every step, so your brain does not have to hold it all at once."