PYTHON / LOOPS
break, continue, and the loop else clause
Control loop flow with break and continue, and use the loop else clause to detect that a loop finished without breaking.
What you will learn
- Exit the innermost loop immediately with break, skipping any else clause
- Jump to the next iteration with continue without leaving the loop
- Read for/while else as 'no break happened' and drop the found-flag variable
- Recognise that continue before a while counter increment hangs the program
Understanding break, continue, and the loop else clause
A loop body normally runs to its last line and then asks the iterator for the next item. break and continue interrupt that rhythm: break abandons the loop entirely and resumes at the first statement after it, while continue abandons only the current iteration and goes straight back to the top for the next item. Both act on the innermost loop that encloses them, which is why a break inside a nested loop leaves the inner loop but not the outer one.
The else clause attached to a for or while loop is the part beginners misread, because it has nothing to do with an if. Python records whether the loop was left by break; if it was not, the else body runs after the loop finishes normally, and if it was, the else body is skipped. The clearest mental model is to read it as 'nobreak': it fires when the loop ran out of items, or when the while condition turned false, including the case where there were zero iterations at all.
This exists because searching is the most common loop shape, and without else you need a bookkeeping variable: set found = False, flip it to True before breaking, then test it afterwards. The else clause lets the interpreter keep that bit for you, so the 'nothing matched' branch sits right next to the loop that failed to match. Note that leaving the loop with return or raise also skips the else, for the same reason break does: the loop never reached its natural end.
def classify(n):
for d in range(2, n):
if n % d:
continue
print(n, "is divisible by", d)
break
else:
print(n, "is prime")
for candidate in (9, 13, 15):
classify(candidate)A loop's else clause runs only when the loop ended without break, which turns break into a signal that something was found.
Worked examples
while ... else with a scan budget
Shows that the else clause of a while loop runs when the condition goes false, but not when break fires.
def first_ok(codes):
i = 0
while i < len(codes):
if codes[i] == "ok":
print("accepted at index", i)
break
i += 1
else:
print("scanned", i, "codes, none accepted")
first_ok(["x1", "x2", "ok", "x3"])
first_ok(["x1", "x2"])Example explained
Line 1The break on the match leaves the loop, so the else clause is skipped and no 'none accepted' line appears.
Line 2In the second call i reaches 2, the condition i < len(codes) becomes false, and the loop ends normally, so else runs.
Line 3i still holds its final value inside the else clause, because a loop does not create its own scope.
Line 4The two calls print different lines from the same loop with no found flag anywhere.
break stops only the inner loop
Demonstrates that break exits one level of nesting, so an outer loop needs its own exit.
grid = [[1, 2, 3], [4, -5, 6], [7, 8, 9]]
found = None
for row in grid:
for value in row:
if value < 0:
found = value
break
if found is not None:
break
print("first negative:", found)Example explained
Line 1The inner break leaves the row scan as soon as -5 is seen.
Line 2Control lands on the 'if found is not None' line, which belongs to the outer loop body.
Line 3Without that second break the outer loop would keep scanning row [7, 8, 9].
Line 4found is checked with 'is not None' rather than truthiness so a legitimate 0 would still count.
return also skips the else
Shows that any early exit from the loop, not just break, suppresses the else clause.
def has_vowel(word):
for ch in word:
if ch in "aeiou":
return True
else:
print("checked all of", word)
return False
print(has_vowel("sky"))
print(has_vowel("cat"))Example explained
Line 1"sky" has no character in "aeiou", so the loop exhausts and the else clause prints its line.
Line 2The function then falls through to return False, which is what gets printed.
Line 3In "cat" the return on 'a' leaves the function at once, so the else clause never runs and nothing is printed before True.
Line 4'y' is not in the string "aeiou", which is why "sky" is treated as vowel-free here.
Important notes
An else clause on a loop that contains no break is pointless: it always runs, so the code belongs after the loop with less indentation.
break and continue are statements, not functions, and using them outside a loop is a SyntaxError rather than a runtime error.
Common mistakes
Reading the else clause as 'runs if the loop body never executed'. It runs after zero iterations and after a full run alike, so an empty list still triggers it.
Putting continue before the i += 1 line in a while loop, which means the counter never changes and the program hangs instead of finishing.
Expecting a single break to escape two nested loops. The outer loop keeps iterating, so the search silently continues over later rows.
Try it yourself
Change, predict, then run
Write a loop over [12, 18, 21, 25] that prints the first number divisible by 5 and breaks, with an else clause printing 'no multiple of 5' otherwise, then rerun it with 25 removed to see both branches.
Open the Python workspaceCheck your understanding
A for loop over a list breaks on the first item that matches, and its else clause prints 'not found'. The list passed in is empty. What is printed?
- 'not found', because the loop finished without ever executing break
- Nothing, because the else clause needs at least one iteration to be considered
- Nothing, because an empty list makes the whole for statement a no-op including else
- A TypeError, because break never ran so the else clause has no result to check
Show answer
The else clause depends only on whether break executed, and with an empty list it never did, so else runs. The tempting option is that else needs an iteration, but Python tracks the break, not the iteration count, so zero iterations and a completed scan are treated the same.