Loops
A loop repeats a block of code. Python has two:
for — do something for each item
prices = [10, 20, 5.5]
for price in prices:
print(price) # runs once per item: 10, then 20, then 5.5for x in <collection> walks through a list (or string, or range) one item at a
time, putting each into x. This is the loop you'll reach for 90% of the time.
❓ Cross-question — "Is
for x in xslike JSfor...inorfor...of?" It'sfor...of— you get the values, not indices. (JSfor...ingives keys/indices — that trap doesn't exist here.) Looping a dict directly gives its keys, sofor k in menu:≈for (const k of Object.keys(menu)). Need the index too? Useenumerate(below).
The accumulator pattern
To total a list, keep a running sum. Set it to 0 before the loop, add to
it inside the loop, use it after:
total = 0 # 1) start empty
for price in prices:
total = total + price # 2) add each item (or: total += price)
print(total) # 3) 35.5Indentation decides what's "inside" the loop. If
return totalis indented under thefor, it runs on the first item and quits early. It must be at the same level astotal = 0— after the loop.
Step through it and watch total climb — this is the pattern behind almost every
"add up the bill" function you'll ever write:
Here is that early-return mistake as running code. It returns after the first price instead of the whole list:
This should print 35, the sum of all three prices. It prints 10. Run it, then fix the indentation.
range() — loop a set number of times
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(1, 4): # 1, 2, 3 (start, stop)
print(i)while — repeat until a condition is false
count = 3
while count > 0:
print(count)
count -= 1 # MUST change, or it loops foreverThe #1 while-loop bug: forgetting to change the condition variable, so it never becomes false → an infinite loop. (Our sandbox will stop it after a few seconds, but avoid it!)
break, continue, and pass
Three little words steer what happens inside a loop:
break— stop the whole loop immediately.continue— skip to the next item, ignoring the rest of this round.pass— do nothing — a placeholder that means "no action here."
pass is the odd one out — it does nothing at all. Python sometimes requires
a statement (you can't leave the block after a : empty), so pass fills the gap.
Use it as a placeholder while you're sketching, or when a branch genuinely has
nothing to do:
breakvscontinuevspass:breakleaves the loop,continuejumps to the next round, andpassjust falls through to the next line.passisn't loop-only — it's Python's "empty statement," used anywhere a line is required but you have none (empty functions,ifbranches,classbodies).
for … else — "we finished without breaking"
A loop can have an else. It's an unusual piece of Python and the name is
genuinely misleading, so read the rule carefully: else runs when the loop
finished normally — that is, when break never fired.
for code in ["SAVE10", "STUDENT"]:
if code == "HALF":
print("found it")
break
else:
print("no HALF code")Read it as "for … then, if nothing broke out". It saves you the "did I find it?" flag variable you'd otherwise have to keep:
Idioms & real-world patterns
Basic for/while loops work, but Python rewards going higher-level. These
patterns are what fluent Python looks like — shorter, faster, clearer.
enumerate — index and item, together
Need the position while looping? Don't manage a counter by hand:
Coming from Java/JS: replaces
for (let i = 0; i < a.length; i++)and JSforEach((x, i) => …)— but the order is(i, x), index first.
zip — walk two lists in lockstep
zip pairs items position-by-position, stopping at the shortest:
List comprehensions — a loop that builds a list
The single most important Python idiom. It turns "make an empty list, loop, append" into one expression:
Add a trailing if to filter:
Coming from Java/JS: this replaces
.map()/.filter()chains.nums.map(x => x*2).filter(x => x > 3)≈[x*2 for x in nums if x*2 > 3].
❓ Cross-question — "Can't I just call
.map()on a list?" No — Python lists have no.map/.filter/.reducemethods. The comprehension is the idiom (the free functionsmap()/filter()also exist, but comprehensions read better), and it builds a real list, not a lazy iterator.
Dict & set comprehensions
Same shape, different braces — build a dict with key: value, or a set
(auto-unique):
⚡ Advanced — generators: build items lazily
A generator expression looks like a list comprehension with () instead of
[], but it doesn't build the whole list — it yields items one at a time, on
demand. Ideal for huge streams or feeding sum()/any()/max():
A generator function uses yield to produce values across calls, pausing and
resuming its own state — memory stays flat no matter how many items:
Coming from Java/JS:
yieldis like a JS generator (function*), and a lazy generator is like a JavaStream— nothing is computed until you iterate it.
❓ Cross-question — "When do I use a generator
(…)vs a list[…]?" Use a list comp[…]when you need the whole thing now — indexing,len, reuse (eager, like a JS array). Use a generator(…)for large/streaming data or a one-pass feed intosum()/any()/max()(lazy, single-use, like a JS generator). Iterating a generator a second time yields nothing.
⚡ Advanced — itertools, the loop power tools
The itertools module has battle-tested building blocks. Two you'll reach for:
🎯 Your turn
Write sum_items(prices) — it adds up a list of prices with a loop and returns the total:
sum_items([10, 20, 5.5])→35.5sum_items([])→0
Hint — start total = 0, then for price in prices: total += price, and return total after the loop.
Then press ▶ Run, tap the Live App try chips to call it with different inputs, and hit ✓ Check. Green = this piece of the app is built. ✅
