Loop control and loop else
Steer loops with break and continue, understand how nested loops behave, and use the else clause on a loop to detect a search that found nothing.
What you will learn
- Use break and continue in for and while loops
- Predict what break does in a nested loop
- Explain when a loop's else clause runs
- Choose between a flag variable and for ... else
On this page
You have already met break and continue. This lesson pins down exactly what they do, especially with nested loops, and introduces a feature that surprises newcomers and is rare in other languages: else on a loop.
break, continue and nesting
breakends the innermost loop that contains it, and execution carries on after that loop.continueabandons the rest of the current pass of the innermost loop and moves on to the next one.
Neither affects an outer loop. Python has no labelled break, so to leave several loops at once you usually move the loops into a function and use return, which the functions module covers.
for i in range(1, 4): for j in range(1, 4): if j == 2: continue if i == 3: break print(i, j)1 11 32 12 3continue skips j == 2 in every row. When i is 3, break stops the inner loop at its very first pass, so nothing prints for row 3, but the outer loop still finishes normally.
Searching with a flag
A search loop has two outcomes: you found what you wanted, or you ran out of places to look. The classic way to tell them apart is a flag: a variable set to False before the loop, flipped to True before break, and tested afterwards.
found = Falsefor letter in "river": if letter == "v": found = True breakprint("flag version:", found)flag version: TrueThe else clause on a loop
A for or while loop can have an else block. It runs when the loop finishes without hitting break. Read it as “no break”: if the loop was cut short, else is skipped; if it ran out of items or its condition went false, else runs.
That makes it a natural fit for searches, where the interesting question is “did I find it?”.
for letter in "river": if letter == "z": print("found z") breakelse: print("else version: no z in the word")else version: no z in the wordIf the word had a z, the loop would print and break, skipping the else. Since none exists, the loop ends normally and the else reports the failure.
A flag is more familiar and often easier to read. for ... else saves a variable but is unfamiliar to many readers, so give it a comment if your team may not know it.
Searching in practice
Nested loops and else together test whether a number is prime. The inner loop looks for a divisor, and break leaves it as soon as one is found. The else runs only when no divisor was found, which means the number is prime.
for n in range(2, 20): for divisor in range(2, n): if n % divisor == 0: break else: print(n, end=" ")print()2 3 5 7 11 13 17 19Look at the indentation: the else lines up with the inner for, not with the if, so it belongs to the loop. For n = 2 the inner range is empty, so the loop ends without a break and 2 counts as prime.
The else can belong to the outer loop too. Here it reports that a search over several numbers found nothing:
for n in range(24, 29): for divisor in range(2, n): if n % divisor == 0: break else: print("first prime:", n) breakelse: print("no primes from 24 to 28")no primes from 24 to 28None of 24 to 28 is prime, so the inner else never runs and the outer loop finishes without a break. Change the range to range(24, 30) and it prints first prime: 29 instead.
Common pitfalls
- Expecting
breakto exit every loop. It only leaves the innermost one. - Misreading the
elseindentation. Anelselined up withforbelongs to the loop. One lined up withifbelongs to theif. Mixing them up flips the logic. - Thinking loop
elsemeans “if the loop was empty”. It runs whenever there was nobreak, including after a normal, non-empty run. - Putting the update after
continuein awhile. The skipped update can cause an infinite loop. - Using
for ... elsewith nobreakin the loop. Then theelsealways runs, so it is pointless. Without abreak, it is just ordinary code after the loop.
Predict what this program prints, then run it. Input: none. Expected output: four numbers on one line.
for n in range(1, 10): if n % 2 == 0: continue if n > 7: break print(n, end=" ")print()Show solution
1 3 5 7Even numbers are skipped by continue. The odd numbers 1, 3, 5 and 7 are printed. When n reaches 9, it is odd, so continue does not apply, but 9 > 7 triggers break before the print.
Given word = "route66", use a for loop with else to print has a digit if any character is a digit, and no digits otherwise. Use the string method isdigit().
Input: route66, then try route. Expected output: has a digit for the first and no digits for the second. The file shows the run for route66.
Show solution
word = "route66"
for character in word: if character.isdigit(): print("has a digit") breakelse: print("no digits")has a digitThe loop stops at the first 6 and break skips the else. With "route" the loop reaches the end without a break, so the else prints no digits.
Find the first prime number from 90 upwards, searching up to 119, and print it as first prime: followed by the number. If none is found, print none found. Use nested loops and else.
Input: none. Expected output: first prime: 97.
Show solution
for n in range(90, 120): for divisor in range(2, n): if n % divisor == 0: break else: print("first prime:", n) breakelse: print("none found")first prime: 97The inner else runs for a number with no divisor, prints it, and the outer break ends the search. The outer else would only run if all 30 numbers had a divisor.
Summary
breakleaves the innermost loop;continueskips to its next pass.- A loop’s
elseruns only if the loop ended withoutbreak, which makes it a “not found” branch for searches. - A flag variable achieves the same result and may read more clearly. Functions will give you a third option, an early
return.
Next: match statements.