1.3Loops (for, while) & comprehensions
The essentials in 30 seconds
- for walks through things: for name in students: — no C-style indices; enumerate() if the index matters, range() to count.
- while = as long as, with an exit: the condition must change (counter, break) — otherwise an infinite loop, interrupted with Ctrl+C.
- Comprehension = simple loop in one line: [x*x for x in numbers if x > 0] — reserved for simple cases, classic loop beyond that.
Running mini-case — Nabil sweeps through his respondents in Algiers
Nabil must greet each respondent, keep asking for a code until it is valid, then extract the squares of positive scores. He first writes for i in range(len(names)) with an index error, then a while True without break that runs forever. He fixes it: plain for name in names, while with a decrementing counter, and a simple comprehension for the squares. The report comes out in one pass, with no infinite loop.
Continuation of cases 1.1-1.2 — Nabil moves from decisions to repetition.
1. for: walk through, don't count
In Python you iterate over things (for name in students:), not indices: the C-style indexed for is a sign you are fighting the language. Need indices? enumerate(); need to count? range() (range(5) gives 0 to 4). break exits the loop, continue skips one round.
Nabil replaces his for i in range(len(names)) with for name in names: and keeps enumerate() to number the report: no more index error.
2. while and comprehensions
while repeats as long as the condition is true (user entry, waiting): guarantee the exit (changing counter, break). The list comprehension [expression for x in sequence if condition] filters and transforms readably in one line — reserved for simple cases (one condition, one expression), otherwise the classic loop wins.
Nabil writes while attempts > 0: with a decrement, then [s**2 for s in scores if s > 0] for positive squares: the retry ends, the extraction fits in one line.
The while with no exit (never do this)
Moral: a loop with no exit is a hamster in its wheel — very busy, never arrived.
🔎 Concrete example — 🔎 Concrete example — Three ways, one right choice each
Each loop in its own territory, like Nabil on his report.
for nom in ["Yasmine", "Nabil"]:
print(f"Hello {nom}")
tentatives = 3
while tentatives > 0:
tentatives -= 1
carres = [x * x for x in range(10)]
print(carres) # [0, 1, 4, ..., 81]
Reading: plain for over items, while with a changing counter, comprehension to build the list.
Lesson: enumerate() when the index really matters — never range(len()) by reflex.
Section vocabulary
- for loop
- Repeats a block for each item of a sequence: for x in sequence. You walk through things, not indices.
Simple example: The respondents greeted one by one by Nabil.
What it is not: a systematic for i in range(len(x)) with x[i].
Reflex: plain for; enumerate() if the index matters.
- range()
- Generates a range of numbers: range(5) gives 0,1,2,3,4. Widely used with for to count or repeat N times.
Simple example: The squares from 0 to 9 computed by Nabil.
What it is not: range(len(list)) to fetch the items.
Reflex: range() to count, not to index.
- while loop
- Repeats a block AS LONG AS the condition stays true. Infinite-loop risk if the condition never changes — guarantee the exit.
Simple example: Nabil's code retry until valid entry.
What it is not: a while True with no break and no changing condition.
Reflex: counter, break or a variable changing each round.
- break / continue
- break exits the loop immediately; continue jumps straight to the next iteration.
Simple example: Nabil's break as soon as the right code is entered.
What it is not: running through the whole list when the target is found.
Reflex: break to stop, continue to skip.
- List comprehension
- Compact writing: [expression for x in sequence if condition] builds a list in one line, pythonically.
Simple example: The squares of positive scores extracted by Nabil.
What it is not: an unreadable nested comprehension over three levels.
Reflex: simple = comprehension; complex = classic loop.
In practice — In practice — Iterating with for, while and comprehensions
- Display the numbers 1 to 10 with "for i in range(1, 11)", then their squares. Add the multiplication table of an entered number.
- Write a while loop that keeps asking for a password until it is correct (take care to change the condition).
- Use break to stop a loop as soon as a condition occurs, and continue to skip even numbers.
- Turn a loop building a list of squares into a list comprehension: squares = [n**2 for n in range(10)]. Compare readability.
Script ready to say — proposing the plain for (30 s)
"I suggest we iterate directly over the items rather than the indices: for name in names — it is more readable and removes the index error. We keep enumerate() only if we really use the number."
Say in code review; show the before/after on the real loop.
Copy-paste template — plain for, while with exit, comprehension
noms = ["Yasmine", "Karim", "Lina"]
for i, nom in enumerate(noms, start=1):
print(f"{i}. Hello {nom}")
tentatives = 3
while tentatives > 0:
code = input("Code? ")
if code == "ALGER":
print("Code accepted")
break
tentatives -= 1
carres_positifs = [s ** 2 for s in [3, -1, 4] if s > 0]
print(carres_positifs) # [9, 16]
Report in Algiers
Like Nabil: plain for + enumerate(start=1) — each respondent greeted and numbered, zero index errors.
Guaranteed retry
A while with a decrementing counter and break on success: the entry always ends up finishing.
One-line extraction
One simple comprehension for positive scores: filter + transform readably, with no 5-line loop.
Targeted skip
A continue to ignore even numbers: skip one round instead of nesting an if — the flow stays flat.
✓ Best practices
- Iterate over things (plain for), enumerate() if the index is used.
- Guarantee the exit of every while (counter, break, changing condition).
- Reserve comprehensions for simple cases, classic loop otherwise.
✗ Common pitfalls
- Systematically writing for i in range(len(x)).
- Starting while True with no break (infinite loop).
- Stacking unreadable nested comprehensions.
Key takeaways
- for walks through a sequence; while repeats as long as a condition is true.
- range() generates number ranges; enumerate() gives index + value.
- break exits the loop; continue moves to the next iteration.
- List comprehensions build a list in one line, pythonically — for simple cases.
48h challenge — apply tomorrow
Convert a for + range(len()) loop into a plain for (template above), add a guaranteed exit to a while, and compact a list-building loop into a simple comprehension. Compare before/after locally. 20 minutes is enough.
- I walk through with a plain for — enumerate() only if the index is used.
- My whiles have a guaranteed exit and my break/continue are placed.
- I write simple, readable comprehensions.
Frequently asked questions
When should I choose for over while?
Use for when you know what you walk through (a list, a range, a file). Use while when you repeat until a condition whose number of iterations you do not know in advance (e.g. "as long as the user does not quit") — while guaranteeing the exit.
My while loop runs forever, why?
It is an infinite loop: the condition stays always true because nothing makes it change inside the block. Make sure a variable in the condition changes each round (counter, break). Ctrl+C interrupts a stuck program.
Which style should you prefer to walk through a list?