for/while…else
An else clause on a loop runs only if the loop finished without hitting a break — genuinely surprising the first time you see it.
for item in iterable:
...
else:
...
Purpose
Both for and while accept an optional else clause. Despite the keyword, it has nothing to do
with if/else — it means “run this if the loop completed normally,” i.e. ran out of items (for
for) or its condition became false (for while) without a break ending it early.
Example
def find_first_negative(numbers: list[int]) -> int | None:
for number in numbers:
if number < 0:
found = number
break
else:
found = None
return found
find_first_negative([4, 7, -2, 9]) -> -2 (break ran; else skipped)
find_first_negative([4, 7, 2, 9]) -> None (loop finished; else ran)
Behavior notes
- The
elseblock runs exactly when the loop’s ownbreakdid not run — that includes the ordinary case of the loop finishing all its iterations, and also the edge case of an empty iterable (aforloop over[]never runs its body, never hitsbreak, and so itselsestill runs). - This is the classic idiom for a “search, then handle not-found” pattern without a separate found-flag variable — precisely what the example above does.
- An exception raised inside the loop body skips the
elseclause entirely, the same way it would skip any other code after the loop.
Common mistakes
- Reading
elsehere as “if the loop’s condition was ever false” (an if/else mental model) — that’s not what it checks. It checks whetherbreakran, nothing else. - Adding a loop’s
elseclause out of habit when nothing in the loop body ever callsbreak— in that case theelseblock always runs and is equivalent to just writing the same code unindented, immediately after the loop.
Implementation notes
This is a language-level control-flow rule, identical across every conforming Python implementation — not a CPython-specific behavior.