skip to content

questions

3

When does the else block of a Python for or while loop actually run?

level: juniorimportance: must knowfreq 40%

answer

  1. It belongs to the loop, not to an if
  2. Ask how the loop ended
  3. Exactly one statement suppresses it
  4. Zero passes still counts as finishing
  5. Read the keyword as nobreak

basics

~20 s

The else clause of a for or while loop runs when the loop ends normally: the iterable is exhausted or the while condition turns false. A break skips it, and an empty iterable still triggers it.

solid answer

~40 s

`for ... else` and `while ... else` attach the `else` to the **loop**, not to any `if` in the body. It runs exactly once, when the loop terminates normally — the iterable runs out, or the `while` condition evaluates false. `break` is the only statement that suppresses it; `continue` does not, and a `return` or a propagating exception skips it by leaving the frame rather than by ending the loop. Zero iterations still counts as normal termination, so a `for` over an empty list runs its `else` immediately. Read the keyword as "nobreak": it is the "the search finished without a hit" branch, which is why search loops and fixed-attempt retry loops are its natural home.

code

python · 11 lines
python
for n in [4, 6, 8]:
    if n % 2:
        print("found odd:", n)
        break
else:
    print("no odd number in the list")

for n in []:
    print("never runs")
else:
    print("else still runs on an empty iterable")

go deeper

for a junior

Be ready to state the rule in one sentence and then trace a short example out loud: the loop's else runs unless a break stopped the loop. Predict the output before you run it.

for a middle

Explain the mechanics rather than the slogan: zero iterations is still normal termination, continue does not suppress the else, and return or an exception bypasses it by leaving the frame instead of ending the loop.

for a senior

Show where the construct earns its place — search-failed and attempts-exhausted branches — and say when you would rewrite it so a reviewer never has to recall the rule to read the control flow.

for a principal

Own the house-style call: whether loop-else is permitted in your codebase, what you require instead, and how you keep control flow reading the same way across teams rather than per author.

Python lets `for` and `while` carry an `else` block, and one fact makes every other detail follow: the `else` is bound to the **loop statement**, not to any `if` inside the body and not to the last thing the body did. The block runs exactly once, when the loop *terminates normally* — the iterator ran out of items (it signalled `StopIteration` internally) or the `while` condition evaluated false. Any exit that is not normal termination skips it. ## The rule in the three shapes you will meet **Exhausted iterable.** The `for` walks its iterable to the end without hitting a `break`, so the `else` runs. This is the search-failed branch: the loop looked at everything and never found what it wanted. **Empty iterable.** Zero iterations is still normal termination — there was never anything to break out of — so a `for` over an empty list runs its `else` immediately. This is the part candidates get wrong most often, because the mental model "the `else` runs after the loop body" quietly assumes a body ran at all. **A `while` whose condition goes false.** `while ... else` follows the same rule with a different termination test: the `else` runs when the controlling expression evaluates false. `while False:` runs its `else` at once, and a `while True:` loop can only ever leave through `break`, `return` or an exception — which makes its `else` unreachable, a genuine thing to flag in review. ## What skips it, and why the distinction matters `break` is the only statement that suppresses the `else` by *ending the loop abnormally*. `continue` does not: it ends the current pass, the loop keeps going, and when the iterable is finally exhausted the `else` still runs. A `return` or a propagating exception also means the `else` never executes, but for a different reason — they leave the enclosing frame or unwind past the loop statement entirely, so control never reaches the `else` at all. State that distinction precisely in an interview: one is a loop-level exit the `else` is defined against; the others are frame-level exits that no part of the loop statement survives. Each loop has its own `else`, so in nested loops an inner `break` suppresses only the inner one. There is no magic opcode behind any of this. Disassembling such a loop with `dis.dis` shows the `else` body compiled as ordinary code on the loop's fall-through path, with `break` compiled as a jump *past* it. That is the whole implementation, and it explains why the empty case behaves as it does: the fall-through path is taken whenever the loop's exit test ends the loop, however many passes that took. ## Read it as "nobreak" The keyword is widely considered misnamed. `else` suggests "otherwise", which invites readers to pair it with an `if`, and the block sits visually far from the `break` it actually pairs with. Mentally substituting the word "nobreak" makes every case fall out: no break happened, so run this. That substitution is also the honest summary of what the block can tell you — it cannot distinguish "searched everything and found nothing" from "there was nothing to search". ## Where it earns its place Two shapes recur. A search loop whose `else` reports failure without needing a flag variable, and a retry loop over a fixed number of attempts whose `else` raises "attempts exhausted" when no attempt succeeded and broke out. Both share the property that the failure branch is genuinely tied to "the loop finished". Anywhere else the `else` is noise: in a loop that contains no `break` at all, the block is unconditionally reached and is exactly equivalent to plain code written after the loop — which is why reviewers and linters treat that form as a defect rather than a style choice. ## What interviewers are actually testing They rarely care whether you would write `for/else` yourself. They care whether you read control flow carefully. The typical prop is a loop whose `break` sits under a condition that is never true, or an iterable that can be empty, and the interviewer watches whether you trace it or pattern-match it. Say the rule, then volunteer the empty-iterable case unprompted; that is the part that separates recall from understanding.

  • Does a continue in the final pass of a Python loop stop that loop's else from running?
    No. `continue` only ends the current pass; the loop still reaches its natural end, so the `else` runs. Only `break` suppresses the `else` as a loop-level exit. A `return` or an uncaught exception also means the `else` never executes, but because control leaves the frame entirely rather than because the loop ended abnormally.
  • Why is the else on a while True loop effectively dead code?
    Because the condition never evaluates false, the only ways out are `break`, `return` and a propagating exception — and all three skip the `else`. So the block can never execute. Seeing one in a review usually means the author expected `else` to pair with an `if` in the body, which is worth raising.
  • In nested Python loops, which loop's else does a break in the inner body affect?
    Only the inner one. Each loop statement carries its own `else`, and a `break` binds to the innermost enclosing loop, so it suppresses that loop's `else`. The outer loop then continues normally and, if it is never broken out of itself, runs its own `else`.

It is the note you leave saying you walked the whole shelf and the book was not there. You only leave it if you reached the end of the shelf — never if you grabbed the book and walked off with it.

saying these in an interview costs you the question

  • Says the else runs after every loop, break included
  • Pairs the else with an if inside the loop body
  • Claims an empty iterable skips the else
  • Thinks continue suppresses the else like break
  • Believes a while True loop can reach its else

context

open as a page

How would you rewrite a Python for/else search loop without the else clause?

level: middleimportance: should knowfreq 28%

basics

~20 s

Two standard rewrites: bind a sentinel before the loop and test it afterwards, or extract the loop into a function that returns on a hit and returns a not-found value at the end. A pure search often collapses to next(generator, default).

open as a page

A for/else scan of a shared document-conversion queue logs "nothing matched" when the list was actually empty — why, and how do you fix it?

level: seniorimportance: nice to knowfreq 15%

basics

~20 s

A loop's else means only that no break happened, which covers both "examined everything and found nothing" and "there was nothing to examine". Zero iterations is normal termination, so an empty snapshot fires the same branch. Distinguish the empty case explicitly.

open as a page