← Back to Program Flow · ← Previous: while Loops and State-Driven Repetition
Loops normally follow their natural repetition rule: a for loop consumes its iterable, and a while loop keeps running while its condition remains truthy. Sometimes a program needs to stop early, skip the rest of one iteration, or distinguish normal completion from an early exit.
This chapter introduces the three tools Python provides for those situations: break, continue, and the optional else clause on loops.
Estimated study time: 110–135 minutes.
By the end of this chapter, you should be able to:
- explain what normal loop completion means for both
forandwhile; - use
breakto terminate the nearest enclosing loop early; - recognize that code after
breakin the same iteration does not run; - use
continueto skip the remaining statements of the current iteration; - explain the different next step after
continueinforandwhile; - update
whilestate safely whencontinueis possible; - use
while Truedeliberately whenbreakexpresses the real stopping rule more clearly; - explain that loop
elsebelongs to the loop, not to an innerif; - predict when loop
elseruns and when abreaksuppresses it; - use
for ... elsefor searches wherebreakmeans a match was found; - use
while ... elsewhen normal condition failure has a meaningful completion path; - recognize that an empty
forloop and an initially falsewhilecondition can still reach loopelse; - explain that
breakaffects only the nearest enclosing loop in nested loops; - choose between
break,continue, loopelse, and ordinary conditions according to intent; - avoid unnecessary control-flow jumps that make a loop harder to read.
Before changing a loop, define what would happen without any special control statement.
A for loop normally ends when its iterator is exhausted:
for number in [1, 2, 3]:
print(number)A while loop normally ends when its condition becomes false:
count = 1
while count <= 3:
print(count)
count += 1break, continue, and loop else only make sense when you understand that normal path first.
break terminates the nearest enclosing for or while loop immediately.
for number in range(1, 6):
if number == 3:
break
print(number)Output:
1
2
When number becomes 3, the loop stops before print(number) can run for that iteration.
Consider:
for item in ["pen", "book", "mug"]:
if item == "book":
break
print(item)
print("Done")Output:
pen
Done
The if decides whether break executes. The break itself transfers control outside the loop.
This code never prints "After break":
for number in [1, 2, 3]:
if number == 2:
break
print("After break")Once break executes, control leaves the loop immediately.
Unreachable statements after an unconditional break should not be left in real code.
Suppose you are searching for one target:
codes = ["PEN", "BOOK", "MUG", "CABLE"]
target = "MUG"
for code in codes:
if code == target:
print("Found")
breakAfter the target is found, examining later items would not change the answer.
If duplicates are possible but only the first match matters, break communicates that policy directly:
values = [4, 7, 7, 9]
for value in values:
if value == 7:
print("First match found")
breakThe second 7 is never examined by the loop body.
This is a poor fit if the task must inspect all values:
scores = [82, 47, 91, 58]If you need to classify every score, ending the loop at the first failing value would lose information.
The control statement should match the real requirement, not merely shorten the code.
count = 1
while count <= 10:
print(count)
if count == 3:
break
count += 1Output:
1
2
3
The original while condition could still be true, but break ends the loop anyway.
A loop whose natural stopping rule occurs inside the body can be written as:
while True:
command = input("Command: ")
if command == "quit":
break
print(command)True keeps the loop eligible to repeat. The meaningful termination rule is the break triggered by "quit".
This is not automatically better than a condition in the while header. Use it when the internal stop condition is genuinely clearer.
This loop has no visible path to termination:
while True:
print("Running")That may be intentional in specialized programs, but for beginner application code it should make you ask:
What event or state change will stop this loop?
If there is no answer, you may have created an accidental infinite loop.
continue skips the rest of the current loop-body execution and starts the next cycle of the nearest enclosing loop.
for number in range(1, 6):
if number == 3:
continue
print(number)Output:
1
2
4
5
The loop itself continues. Only the remainder of the iteration for 3 is skipped.
Compare the intent:
break -> stop this loop
continue -> skip the rest of this iteration and keep looping
Confusing the two changes the entire control-flow shape.
scores = [82, 47, 91, 58, 76]
for score in scores:
if score < 60:
continue
print(f"Passing score: {score}")Output:
Passing score: 82
Passing score: 91
Passing score: 76
Failing scores are skipped, while the remaining values still reach the main action.
Without continue:
for score in scores:
if score >= 60:
print(f"Passing score: {score}")With continue:
for score in scores:
if score < 60:
continue
print(f"Passing score: {score}")Both can be clear. The second form is often useful when several early checks reject an item before a longer main path.
This is a readability choice, not a rule that continue is always superior.
for letter in "ABC":
if letter == "B":
continue
print(letter)Output:
A
C
After skipping the rest of the B iteration, the for loop requests the next item from its iterator.
number = 0
while number < 5:
number += 1
if number == 3:
continue
print(number)Output:
1
2
4
5
After continue, Python returns to the while condition before another body execution.
This pattern is dangerous:
number = 0
while number < 5:
if number == 2:
continue
number += 1When number reaches 2, continue runs before the update. The condition remains true and number stays 2, so the loop repeats forever.
A useful review question is:
Can every path through this while body still make progress toward termination?
Do not add a jump merely because Python provides one.
for number in range(1, 6):
if number != 3:
print(number)may be perfectly readable compared with:
for number in range(1, 6):
if number == 3:
continue
print(number)Choose the shape that communicates the loop's main path most clearly.
Both for and while may have an optional else clause.
For a for loop:
for item in iterable:
statement
else:
normal_completion_statementFor a while loop:
while condition:
statement
else:
normal_completion_statementThe key rule is not “the condition was false.” The general rule is:
The loop else runs when that loop finishes without executing a break.
for number in [1, 2, 3]:
print(number)
else:
print("Finished normally")Output:
1
2
3
Finished normally
The iterable was exhausted and no break occurred, so the else suite runs.
for number in [1, 2, 3]:
if number == 2:
break
else:
print("Finished normally")There is no output from the else clause because break terminated that loop.
for number in [1, 2, 3]:
if number == 2:
continue
print(number)
else:
print("Finished without break")Output:
1
3
Finished without break
continue changes an iteration, not the loop's final completion category.
Look carefully at the indentation:
for name in names:
if name == target:
print("Found")
break
else:
print("Not found")The else aligns with for, not with if.
That visual relationship is essential to reading this syntax correctly.
names = ["Ari", "Mina", "Leo"]
target = "Nora"
for name in names:
if name == target:
print(f"Found {target}")
break
else:
print(f"{target} was not found")Output:
Nora was not found
The meaning is compact:
match found -> break -> skip else
no match -> no break -> run else
A flag-based search can work:
found = False
for name in names:
if name == target:
found = True
break
if not found:
print("Not found")The loop-else form represents the same control-flow fact directly:
for name in names:
if name == target:
break
else:
print("Not found")Use the version that your readers can understand reliably. Loop else is a real Python feature, but it can be unfamiliar to some teams.
for item in []:
print(item)
else:
print("No break occurred")Output:
No break occurred
The loop body ran zero times, but the loop still completed without break.
count = 1
while count <= 3:
print(count)
count += 1
else:
print("Condition became false")Output:
1
2
3
Condition became false
This is normal completion for that while loop.
count = 1
while count <= 5:
if count == 3:
break
count += 1
else:
print("Condition became false")The else suite does not run because break ended the loop first.
count = 5
while count < 3:
print(count)
else:
print("Loop completed without break")Output:
Loop completed without break
The body executed zero times, but no break occurred.
Loop else is sometimes informally described as a “not found” block because searches are a common use case.
That description is too narrow.
The actual control-flow fact is:
loop ended without break -> else runs
loop ended through break -> else is skipped
The meaning of “success,” “failure,” “found,” or “not found” comes from your program, not from Python itself.
rows = [[1, 2], [3, 4]]
for row in rows:
for value in row:
if value == 2:
break
print(value)Output:
1
3
4
The break exits the inner loop only. The outer loop continues with the next row.
In nested loops, continue advances the nearest loop that syntactically contains it.
That can become difficult to read if several nested levels contain control jumps.
When nesting grows, prefer making the control flow explicit rather than stacking many break and continue statements.
Nested loops may each have their own else clause, but indentation determines which loop owns which clause.
For beginners, avoid dense combinations until the simpler shape is completely clear.
One loop, one search goal, and one meaningful else is usually easier to study.
This does not exit both loops:
for row in rows:
for value in row:
if value == target:
breakOnly the inner loop ends.
Later phases introduce functions, which often provide cleaner ways to organize larger searches without complicated nested-loop control.
while condition:
if skip_this_cycle:
continue
update_state()If update_state() is necessary for termination, the skipped path may never make progress.
When reviewing a while loop, trace every branch that can reach continue.
This indentation:
for item in items:
if condition:
break
else:
statementmeans the else belongs to for.
Moving the else under the if would create a different program with different behavior.
If code must always run after a loop regardless of whether break occurred, place it after the loop:
for item in items:
if should_stop:
break
print("Cleanup message")Do not use loop else for unconditional post-loop work, because break would skip it.
A loop with many control jumps can become a maze:
condition -> continue
condition -> break
condition -> continue
condition -> nested break
These statements are useful because they are precise, not because more of them makes code better.
Prefer a small number of clearly motivated exits and skips.
codes = ["PEN", "BOOK", "MUG", "CABLE"]
target = "MUG"
for code in codes:
print(f"Checking {code}")
if code == target:
print(f"Found {target}")
breakOutput:
Checking PEN
Checking BOOK
Checking MUG
Found MUG
Repository example: examples/break_search.py
scores = [82, 47, 91, 58, 76]
for score in scores:
if score < 60:
continue
print(f"Passing score: {score}")Output:
Passing score: 82
Passing score: 91
Passing score: 76
Repository example: examples/continue_filtering.py
names = ["Ari", "Mina", "Leo"]
target = "Nora"
for name in names:
if name == target:
print(f"Found {target}")
break
else:
print(f"{target} was not found")Output:
Nora was not found
Repository example: examples/loop_else_search.py
Create a list of fictional task codes:
task_codes = ["A10", "B20", "SKIP", "C30", "STOP", "D40"]Write one loop that:
- uses
continuewhen the value is"SKIP"; - uses
breakwhen the value is"STOP"; - prints every other task code that is reached;
- adds a loop
elsethat prints"All tasks processed"only if the loop finishes withoutbreak.
With the list above, the expected output is:
A10
B20
C30
Then remove "STOP" from the list and predict what changes before running the program.
Before moving on, confirm that you can explain each statement without running the code:
-
breakterminates the nearest enclosingfororwhileloop. - statements later in the same iteration are skipped after
break. -
continueskips the rest of the current iteration without terminating the loop. - in
for,continueproceeds toward the next item. - in
while,continuereturns to the condition test. - a
whileloop must still update relevant state on paths that can reachcontinue. -
while Trueis appropriate when an internalbreakexpresses the real stop rule clearly. - loop
elsealigns with and belongs to the loop. - loop
elseruns when that loop completes withoutbreak. -
breaksuppresses the associated loopelse. -
continuedoes not by itself suppress loopelse. - an empty
forcan still execute itselse. - an initially false
whilecan still execute itselse. - in nested loops,
breakandcontinueaffect the nearest enclosing loop. - loop-control statements should clarify intent rather than create unnecessary jumps.
| Need | Typical tool |
|---|---|
| Stop the current loop immediately | break |
| Skip the rest of one iteration | continue |
| Repeat indefinitely until an internal stop rule | while True + break |
Run a block only when no break ended the loop |
loop else |
| Search until a match is found | for + condition + break |
| Handle “not found” after a complete search | for ... else |
| Skip rejected items while keeping later items | continue |
| Always run code after a loop | ordinary statement after the loop |
Remember the progression:
normal repetition → early exit → skip one cycle → distinguish normal completion from break
The next chapter is Choosing and Combining Program Flow.
You now have the main selection and repetition tools of Phase 4: conditions, if, match, for, iteration helpers, while, break, continue, and loop else. The final chapter of the phase will focus on choosing among them and combining them without turning control flow into a maze.