1.3 · Loops (for, while) & comprehensions

Level 1 · Language basics

1.3Loops (for, while) & comprehensions

Goal: iterate efficiently with for and while, control flow with break/continue, and discover list comprehensions.
Estimated time: 14 min · self-paced reading · If you only have 5 min: read “The essentials in 30s” + the diagram.

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.

Common misinterpretation: "for i in range(len(x)) everywhere" or "while True with no exit, it'll be fine". No. Iterating by index when you want the items complicates and breaks (enumerate() if the index really matters). And a while whose condition never changes is an infinite loop blocking the program: counter, break or a changing condition — always a guaranteed exit.
Repeating correctly Walk through, as-long-as, compact for (walk through) Overthings, enumerate if indexwhile (as long as) Changingcondition, guaranteed exitComprehension (simple) Oneline, one condition max
Walk through, as-long-as, compact
Text version of the diagram (SEO / screen readers / translation): 1) Walk through: Nabil writes for name in names — the things directly, enumerate() to number, range() to count. 2) Repeat: while with a decrementing counter and a backup break — the condition changes each round. 3) Compact: one simple comprehension to filter and transform in one line, classic loop as soon as it gets complicated. Lesson: things with for, an exit with while, simple stuff in comprehensions.

The while with no exit (never do this)

"My program has been running for 20 minutes, that means it is thinking hard, right?"
Verdict: no — it is a while True with no break looping over nothing. Ctrl+C, then a counter.
"I wrote three nested comprehensions, that is senior code."
Verdict: it is a puzzle, not code — a classic loop would be re-read in 10 seconds.

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

  1. Display the numbers 1 to 10 with "for i in range(1, 11)", then their squares. Add the multiplication table of an entered number.
  2. Write a while loop that keeps asking for a password until it is correct (take care to change the condition).
  3. Use break to stop a loop as soon as a condition occurs, and continue to skip even numbers.
  4. Turn a loop building a list of squares into a list comprehension: squares = [n**2 for n in range(10)]. Compare readability.
You repeat actions with for and while, control flow with break/continue, and write your first list comprehensions.

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.

Section exit checklist
  • 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.
Self-assessment 1-5: do my loops iterate over things rather than indices?Self-assessment 1-5: can each while actually finish?

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.

Check your understanding

Which style should you prefer to walk through a list?

Additional resources (optional, to go further)

Level 1 examFresh, harder questions to test what you've learned