Learning Goals
3 minBy the end of this lesson you can:
- Trace through a short Python snippet on paper, line by line, tracking every variable's value.
- Predict the output of common Level 1 patterns: loops, list mutations, function returns, string slicing, boolean conditions.
- Spot the moments where Python's rules trip up your intuition — empty list as
False, integer division differences, list aliasing.
The Rules
3 minOpen your notebook or a blank text file as a scoring sheet. For each snippet:
- Read it — slowly, line by line.
- Write your prediction on paper or the scoring sheet. Be specific — exact text, exact order, with quotes/brackets if they appear.
- Run the snippet and compare.
- Score yourself: ✓ for an exact match, ✗ for any mismatch.
Aim for 6/8 to call it a good day. 7/8 means you're reading Python like a native. 8/8 — start helping your classmates.
It's very tempting to just run the snippet and read the output. Don't. The whole point of this lesson is to build your mental Python interpreter. Running before predicting trains nothing.
The Eight Snippets
35 minSnippet 1 · for-loop basics
for i in range(3): print(i, "Mango")
Show the answer
0 Mango 1 Mango 2 Mango
range(3) is 0, 1, 2 — three values, never reaches 3. Most-asked-about gotcha in PY-L1-13.
Snippet 2 · slice with negative end
word = "Selamat" print(word[1:-1])
Show the answer
elama
Start at index 1 (e), stop before index -1 (t). So we get characters at 1, 2, 3, 4, 5 — "elama". Slicing is half-open on the stop side; negative indices count from the end.
Snippet 3 · list mutation in a loop
nums = [1, 2, 3] total = 0 for n in nums: total = total + n nums.append(n) # mutates the list we're iterating! print(total) print(nums)
Show the answer (it's weird)
(infinite loop — never reaches the print)
You can't safely append to a list while you're iterating it — Python keeps revisiting the new items, forever. The loop never ends. This is the "don't edit what you're reading" rule, dramatically.
Snippet 4 · boolean short-circuit
x = 5 y = 0 if x > 0 and y > 0: print("both") elif x > 0 or y > 0: print("either") else: print("neither")
Show the answer
either
x > 0 is True; y > 0 is False. True and False is False, so the first branch skips. True or False is True, so the elif matches. PY-L1-10 in one short test.
Snippet 5 · function return capture
def shout(name): print(name.upper()) result = shout("Aisyah") print("Result is", result)
Show the answer
AISYAH Result is None
shout prints but never returns, so result ends up None. The function quietly returned the "nothing" value. PY-L1-29's big idea, hidden in plain sight.
Snippet 6 · empty list is falsy
bag = [] if bag: print("Heavy.") else: print("Empty.") bag.append("torch") if bag: print("Heavy.") else: print("Empty.")
Show the answer
Empty. Heavy.
An empty list is "falsy" — Python treats it as False in a boolean context. As soon as anything's in the list, it's "truthy". This is why if bag: is a clean way to ask "is there anything in the bag?" without writing if len(bag) > 0.
Snippet 7 · integer math vs float math
print(7 / 2) print(7 // 2) print(7 % 2) print(7 ** 2)
Show the answer
3.5 3 1 49
The four divide-flavoured operators from PY-L1-04. / is regular division (always returns a float). // is integer division (floor). % is the remainder. ** is exponentiation. Easy to mix up — write the four rules on a sticky note.
Snippet 8 · list aliasing trap
a = [1, 2, 3] b = a c = list(a) a.append(4) print(a) print(b) print(c)
Show the answer
[1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3]
b = a aliases — both names point to the same list, so the append affects both. c = list(a) makes a real copy, untouched by the append. The same lesson as Bug 4 yesterday, in a snapshot.
0-3: re-read the lessons referenced and try again next week — that's why these are flagged. 4-5: solid but with blind spots. 6+: you're reading Python like a programmer.
The Three Habits of Output-Predictors
5 min1. Trace, don't skim
For every snippet, write down the value of every variable after every line. It feels slow at first — three minutes per snippet — but speeds up dramatically with practice. After 50 such traces, you do it in your head in seconds.
2. Slow down at boundaries
Bugs live at the edges: the first and last iterations of loops, empty inputs, off-by-one indices, equality checks (> vs >=). When tracing, always run the snippet in your head on the smallest possible input first — range(0), [], 0. If the snippet survives the edge cases, the middle is usually fine.
3. Trust the printer
Many wrong predictions come from imagining what the programmer meant instead of what they wrote. name.upper() with no print outputs nothing — it computes a value and throws it away. Predict literally what the code says, not what feels right.
Self-Check
5 minMake a tally on your scoring sheet. For every snippet you got wrong, note which of the eight bug families from PY-L1-42 was hiding there. Common mappings:
- Snippet 1, 7 → off-by-one or range/divide trap (memorise edge rules)
- Snippet 2 → string slicing rules (re-read PY-L1-24)
- Snippet 3, 8 → list aliasing/mutation traps (re-read PY-L1-31, PY-L1-40)
- Snippet 4, 6 → boolean logic gotchas (re-read PY-L1-09, PY-L1-10)
- Snippet 5 →
printvsreturn(re-read PY-L1-29)
Pick the one you missed most badly. Open the referenced lesson tonight and re-read the worked example.
Bonus · The Sneaky Two
8 minFor students who finish early, two extra snippets that have caught even strong students.
Bonus A · loop variable after the loop
for i in range(5): pass print(i)
Show the answer
4
The loop variable persists after the loop ends, holding the last value it took. range(5) ended with i = 4. Surprising — but it's why people sometimes use the loop variable outside the loop. Some other languages erase it; Python keeps it.
Bonus B · string "in"
print("at" in "katak") print("ak" in "katak") print("k" in "katak") print("KAT" in "katak")
Show the answer
False True True False
in on a string checks for substring presence — and it's case-sensitive. "at" isn't a substring of "katak" (the letters are there but not adjacent in that order); "ak" is; one-letter checks like "k" work like "does any character match". Uppercase fails. The same in from PY-L1-15 list-membership, but watching for case is the same hygiene rule from PY-L1-23.
Recap
3 minPredicting output is reading code with conviction. The same skill that makes you a good debugger makes you a good code reviewer, and eventually a good architect. Today's eight snippets cherry-picked the Level 1 ideas that most often trip beginners up: range boundaries, slice semantics, the =/== distinction, the immutability of strings, the aliasing of lists, the truthiness of containers, the difference between / and //, and the silent None from forgotten returns. Tomorrow is the speed round — same kind of snippets, but you're asked to write them yourself, against the clock.
Vocabulary Card
- tracing
- Writing down every variable's value after every line, by hand. The fundamental debugging move.
- truthy / falsy
- Values that behave like
TrueorFalsein conditions. Empty containers are falsy; non-empty ones are truthy. - floor division
// - Integer division. Always returns a whole number, rounding down.
- loop-variable persistence
- In Python, the variable used as a for-loop counter still exists after the loop, holding the last value.
- substring
in - For strings,
x in stests whetherxappears as a contiguous run of characters ins.
Homework
4 minTwo short jobs tonight, both about getting faster.
- Re-trace. Pick the three snippets you missed in class. Without running them, re-trace each on paper line by line and write the predicted output. Then run them. Aim for 3/3 this time.
- Build the deck. Make a file
my_predictions.pywith three of your own snippets — each one between 3 and 10 lines, each one demonstrating a specific gotcha. At the top of each, put a comment# Expected: ...with the right answer. Tomorrow's speed round will use snippets like these.
Bring both files. PY-L1-44 is the speed round — ten micro-problems, you write the code.
Sample · my_predictions.py
# my_predictions.py — three Level-1 gotchas of my own. # 1) Negative slicing of strings # Expected: dom word = "kingdom" print(word[-3:]) # 2) List + list (concat, not addition) # Expected: [1, 2, 3, 4] a = [1, 2] b = [3, 4] print(a + b) # 3) Range with a negative step # Expected: 10 8 6 4 2 (each on its own line) for n in range(10, 0, -2): print(n)
Good prediction snippets stay short and demonstrate one idea each. Negative slicing, list +, and reverse range are all PY-L1 ideas worth pinning down — and they're each one line of code, with a clear "Expected:" line right above. Use this pattern for any concept you want to drill.