break, continue, loop else clause
Overview
Python provides three keywords that control iteration flow inside loops. - `break`: Exits the loop immediately and skips all remaining iterations. - `continue`: Skips the rest of the current iteration and jumps directly to the next item. - `else`: A block attached to the loop that runs only if the loop completes naturally without hitting a `break`. Using `break` allows you to stop searching as soon as you find what you need. for user in users: if user['role'] == 'admin': admin = user break Using `continue` is useful for filtering out invalid or unneeded data early in an iteration. for record in records: if record['status'] == 'deleted': continue process(record) The loop `else` clause is the Pythonic way to express a "search completed with no match found" scenario without using a boolean flag variable. for route in routes: if route == '/admin': print('found') break else: print('/admin not registered') A common trap is expecting the `else` block to run on every loop exit. The `else` block is completely skipped if the loop was terminated by a `break` statement. for item in [1, 2, 3]: if item == 2: break else: print("This never prints because the loop hit a break!")
Without `break`, you must add a boolean flag to track whether a search succeeded. Without `continue`, you must nest all your processing inside an `if` block. The loop `else` pattern eliminates an entire class of 'found it / not found' flag variables.
Where used: Searching for a matching config entry, Skipping soft-deleted records before processing, Validating a list of permissions — stop on first failure or confirm all passed
Why learn this
- Eliminating flag variables (`found = False` ... `if not found:`) with the loop `else` clause
- Writing clean early-exit search loops in FastAPI handlers and validation pipelines
Code walkthrough
routes = ['/health', '/users', '/items']
for route in routes:
if route == '/admin':
print('admin route found')
break
else:
print('/admin not registered')
Focus: The loop checks all three routes without hitting `break`, so the `else` clause runs and prints `'/admin not registered'` — no flag variable needed.
Common mistakes
- Thinking loop `else` means 'if the loop body never ran': The `else` clause runs when no `break` occurred — even if the loop executed zero iterations. It is about `break`, not about iteration count.
- Using `break` in a nested loop expecting it to exit the outer loop: `break` only exits the innermost loop. To exit an outer loop, either restructure with a function and `return`, or use a flag variable.
- Using `continue` when an early `return` inside a function is cleaner: If the loop body is inside a function, using `return` at the top is often more readable than `continue`. Reserve `continue` for loops where you must keep iterating.
Glossary
- iteration
- One single cycle of repeating a set of instructions, like going through one item in a list, e.g. `for item in [1, 2, 3]` has three iterations.
- boolean flag
- A variable that holds either `True` or `False`, often used to track if a specific condition was met, e.g. `found = False`.
Recall questions
- What does `break` do to a loop?
- What does `continue` do inside a loop body?
- When does a loop's `else` clause run?
- What problem does the loop `else` clause solve cleanly?
Understanding checks
What is the output of this code?
It prints 1, 3, and 'done'.
When `x == 2`, `continue` skips the rest of the loop body (skipping `print(x)`). The loop finishes normally without any `break`, so the `else` block executes.
What is the output of this code?
It prints 'empty'.
The loop body never executes because the list is empty, so `break` is never encountered. Therefore, the `else` block runs.
Practice tasks
Remove the Flag Variable
The function `first_active` currently uses a boolean flag variable to check if an active user was found. Refactor the code to remove the `found` flag. Use a `break` statement and the loop's `else` clause instead.
Challenge
Permission validator
Write `check_permissions(required, granted)` that iterates `required` permissions and uses `continue` to skip any already in `granted`, then prints `'missing: <perm>'` for each absent one. After the loop, if every required permission was in `granted` (i.e., no `'missing'` line was printed), use the loop `else` clause to print `'all permissions satisfied'`. Test with a full match and a partial match.
Continue learning
Previous: for and while loops
Previous: if/elif/else and Python truthiness
Next: List Comprehensions