Loop Control: break, continue, and Loop else
Loop Control: break, continue, and Loop else
After reading this chapter, you will master loop execution interruption using break and continue, eliminate boolean search flags using the loop else clause, break out of nested loop structures cleanly, and handle pipeline filtering without nested conditional blocks.
Mental model
Python provides three control keywords that alter standard loop iteration:
Loop Control Keywords:
1. continue ──▶ Immediately skips the remaining statements in the current iteration;
jumps directly to the next iteration evaluation.
2. break ──▶ Immediately aborts the entire loop;
jumps to the first statement outside the loop.
3. else ──▶ Executes IF AND ONLY IF the loop finished all iterations
without hitting an explicit break statement!
The Loop 'else' Contract:
for item in sequence:
if item == target:
break ─────────────────────────┐ (Bypasses loop 'else'!)
else: │
# Runs ONLY if target was NOT found│
print("Item missing!") │
▼
[ Resume Outer Execution ] ◀───────────┘
Minimal example
Save as loop_control_statements.py:
# loop_control_statements.py
def inspect_packet_batch(packets: list[dict[str, str | int]]) -> None:
print(f"Inspecting batch of {len(packets)} network packets...")
for pkt in packets:
# 1. 'continue' skips empty or malformed packets
if pkt.get("size", 0) <= 0:
print(f" [Skip] Packet {pkt.get('id')} has 0 bytes. Continuing.")
continue
# 2. 'break' immediately terminates loop on critical security violation
if pkt.get("flags") == "MALICIOUS":
print(f" [SECURITY ALERT] Malicious payload detected on ID {pkt['id']}! Terminating inspection immediately.")
break
print(f" [OK] Packet {pkt['id']} verified ({pkt['size']} bytes).")
else:
# 3. Loop 'else' executes ONLY if loop completed without hitting 'break'
print(" [SUCCESS] All packets verified clean. Batch approved for forwarding.")
def main() -> None:
# Test clean batch
clean_batch = [
{"id": 101, "size": 64, "flags": "SYN"},
{"id": 102, "size": 0, "flags": "ACK"}, # Skipped via continue
{"id": 103, "size": 128, "flags": "ACK"},
]
print("--- Test 1: Clean Batch ---")
inspect_packet_batch(clean_batch)
# Test malicious batch
dirty_batch = [
{"id": 201, "size": 64, "flags": "SYN"},
{"id": 202, "size": 512, "flags": "MALICIOUS"}, # Aborted via break
{"id": 203, "size": 64, "flags": "ACK"},
]
print("\n--- Test 2: Dirty Batch ---")
inspect_packet_batch(dirty_batch)
if __name__ == "__main__":
main()Run via uv run python loop_control_statements.py:
--- Test 1: Clean Batch ---
Inspecting batch of 3 network packets...
[OK] Packet 101 verified (64 bytes).
[Skip] Packet 102 has 0 bytes. Continuing.
[OK] Packet 103 verified (128 bytes).
[SUCCESS] All packets verified clean. Batch approved for forwarding.
--- Test 2: Dirty Batch ---
Inspecting batch of 3 network packets...
[OK] Packet 201 verified (64 bytes).
[SECURITY ALERT] Malicious payload detected on ID 202! Terminating inspection immediately.
Worked examples
Case 1: Search and Validate Without Boolean Flags (for ... else)
In languages like C or Java, checking whether a list contains an item matching specific criteria requires setting a boolean flag (found = False). Python’s loop else eliminates this boilerplate:
# target_finder_clean.py
def find_available_worker(workers: list[dict[str, str | int]]) -> None:
# Search for an idle worker with CPU load under 20%
for w in workers:
if w["status"] == "IDLE" and w["cpu_pct"] < 20:
print(f"Dispatching task to worker: {w['name']} (CPU: {w['cpu_pct']}%)")
break
else:
# Executes only if no worker matched
print("CAPACITY ALERT: No available idle worker found across cluster!")
if __name__ == "__main__":
cluster = [
{"name": "worker-01", "status": "BUSY", "cpu_pct": 85},
{"name": "worker-02", "status": "IDLE", "cpu_pct": 95},
{"name": "worker-03", "status": "BUSY", "cpu_pct": 40},
]
find_available_worker(cluster)Run:
uv run python target_finder_clean.pyOutput:
CAPACITY ALERT: No available idle worker found across cluster!
Case 2: Breaking Out of Nested Loops
A break statement only terminates the innermost loop. To exit multiple nested loops simultaneously without clumsy flag variables, encapsulate the nested loops in a function and use return:
# nested_loop_exit.py
def locate_corrupted_block(matrix: list[list[int]]) -> tuple[int, int] | None:
"""Scan a 2D matrix and return (row, col) coordinates of first negative value."""
for row_idx, row in enumerate(matrix):
for col_idx, value in enumerate(row):
if value < 0:
# 'return' instantly exits BOTH loops cleanly!
return (row_idx, col_idx)
return None
if __name__ == "__main__":
storage_grid = [
[100, 200, 300],
[400, -999, 600], # Corrupted block at row 1, col 1
[700, 800, 900],
]
coord = locate_corrupted_block(storage_grid)
print(f"Corrupted block coordinates: {coord}")Run:
uv run python nested_loop_exit.pyOutput:
Corrupted block coordinates: (1, 1)
Pitfalls
Pitfall 1: Assuming break Exits All Nested Loops
Calling break inside an inner loop returns control to the outer loop, not the code outside the outer loop:
for outer in range(3):
for inner in range(3):
if inner == 1:
break # Exits 'inner' loop only! 'outer' continues iterating!To exit both, encapsulate the nested loops inside a function and use return, or use a custom exception.
Pitfall 2: Confusing Loop else with if else
A loop else does not mean “run if the loop didn’t execute”. If a loop iterates over an empty list (for x in []:), it completes 0 iterations without hitting break, so the else block does execute! Think of loop else as “no-break”.
Exercises
- Write a prime number checker using
for ... in range(2, n): ... break else:to determine whether \(n\) is prime without boolean flags. - Given a list of log entries, use
continueto filter out all entries that do not contain"ALERT"or"CRITICAL". - Demonstrate that iterating over an empty list
for item in []: break else: print("RUN")executes theelseblock. - Implement a function that scans a 3D tensor and uses
returnto break out of all three nested loops when a NaN value is encountered.
Further reading
- Python Language Reference: The
breakandcontinuestatements. - Raymond Hettinger: Transforming Code into Beautiful, Idiomatic Python (The for-else idiom).