While loops execute a block of code repeatedly as long as a condition is True โ unlike for loops which iterate over a fixed sequence, while loops are used when the number of iterations is not known in advance. Python adds two loop control tools โ break (exit the loop immediately) and continue (skip to the next iteration) โ and a unique else clause on loops that runs only when the loop completes normally without hitting a break. In FastAPI you will use while loops for retry logic, polling, and processing streaming data, and the else clause for search patterns where you need to know whether a break was triggered.
Basic while Loop
# Repeat as long as condition is True
count = 0
while count < 5:
print(count)
count += 1 # Must update the condition variable!
# 0, 1, 2, 3, 4
# Countdown
n = 5
while n > 0:
print(n)
n -= 1
print("Done!")
# 5, 4, 3, 2, 1, Done!
# while True โ infinite loop controlled by break
attempts = 0
while True:
user_input = input("Enter a number: ")
if user_input.isdigit():
break # exit loop when valid input received
print("Invalid โ try again")
attempts += 1
if attempts >= 3:
print("Too many attempts")
break
while loop must have a mechanism to eventually make its condition False, or a break statement that exits the loop. Forgetting to update the loop variable is the most common cause of infinite loops โ the program hangs forever consuming 100% CPU. If your program seems frozen during development, press Ctrl+C to interrupt it and check your while loop logic.while True: ... break pattern (also called a “loop and a half”) is the cleanest way to handle “check condition after at least one iteration” scenarios โ like reading user input or polling an endpoint until a condition is met. It is more readable than the do...while pattern that JavaScript uses, which Python does not have. Use this pattern in FastAPI background tasks that poll for a status change.continue and break only affect the innermost loop. If you have nested loops and want to break out of the outer loop, you need a different approach โ either use a flag variable, refactor into a function and use return, or use Python 3.10’s match statement. There is no break 2 or labelled break in Python like in some other languages.break โ Exit the Loop Early
posts = [
{"id": 1, "title": "First", "published": True},
{"id": 2, "title": "Second", "published": False},
{"id": 3, "title": "Target", "published": True},
{"id": 4, "title": "Fourth", "published": True},
]
# Find the first published post with id > 2
found = None
for post in posts:
if post["id"] > 2 and post["published"]:
found = post
break # stop searching โ we found it
print(found) # {"id": 3, "title": "Target", "published": True}
# break in while โ retry with limit
import time
def fetch_with_retry(url: str, max_retries: int = 3):
attempts = 0
while attempts < max_retries:
try:
response = requests.get(url, timeout=5)
if response.status_code == 200:
return response.json()
break # non-200 but not an exception โ stop retrying
except requests.Timeout:
attempts += 1
time.sleep(1)
return None # failed after retries
continue โ Skip to Next Iteration
posts = [
{"id": 1, "title": "Draft", "published": False},
{"id": 2, "title": "Published", "published": True},
{"id": 3, "title": "Another", "published": True},
]
# Process only published posts
for post in posts:
if not post["published"]:
continue # skip unpublished โ go to next iteration
print(f"Processing: {post['title']}")
# Processing: Published
# Processing: Another
# Skip invalid values
data = [1, None, 3, None, 5]
total = 0
for value in data:
if value is None:
continue # skip None values
total += value
print(total) # 9
The Loop else Clause
# The else clause runs if the loop completes WITHOUT a break
# It does NOT run if break was triggered
# Common use: search โ did we find what we were looking for?
users = [
{"id": 1, "email": "alice@example.com"},
{"id": 2, "email": "bob@example.com"},
]
target_email = "charlie@example.com"
for user in users:
if user["email"] == target_email:
print(f"Found: {user}")
break
else:
# This runs because no break was triggered
print("User not found")
# User not found
# Compare: if target_email were "alice@example.com":
# loop finds it, break fires, else block is SKIPPED
# while loop also supports else
attempts = 0
while attempts < 3:
result = try_operation()
if result:
break
attempts += 1
else:
print("Operation failed after 3 attempts") # runs if no break
Nested Loops
# Multiplication table
for i in range(1, 4):
for j in range(1, 4):
print(f"{i}ร{j}={i*j}", end=" ")
print() # newline after each row
# 1ร1=1 1ร2=2 1ร3=3
# 2ร1=2 2ร2=4 2ร3=6
# 3ร1=3 3ร2=6 3ร3=9
# break only exits the INNER loop
for i in range(3):
for j in range(3):
if j == 1:
break # exits inner loop only
print(f"({i},{j})")
# (0,0)
# (1,0)
# (2,0)
# To break out of both loops โ use a flag
found = False
for i in range(10):
for j in range(10):
if i * j == 42:
found = True
break
if found:
break
print(f"Found at i={i}, j={j}")
Common Mistakes
Mistake 1 โ Forgetting to update the loop variable (infinite loop)
โ Wrong โ count never changes, loop runs forever:
count = 0
while count < 5:
print(count)
# Forgot: count += 1 โ infinite loop! Press Ctrl+C to stop
โ Correct โ always update the condition variable:
count = 0
while count < 5:
print(count)
count += 1 # โ condition will eventually become False
Mistake 2 โ Misunderstanding the else clause
โ Wrong โ thinking else runs when the condition becomes False:
for i in range(3):
print(i)
else:
print("Loop done") # This runs โ but it also runs with break!
โ Correct โ else only runs when NO break occurred:
for i in range(3):
if i == 1:
break
else:
print("No break") # NOT printed โ break was triggered
Mistake 3 โ Assuming break exits all nested loops
โ Wrong โ expecting break to exit the outer loop:
for i in range(3):
for j in range(3):
if j == 1:
break # only exits inner loop!
print(f"i={i}") # this still runs for all i values
โ Correct โ use a flag variable to break multiple loops.
Quick Reference
| Pattern | Code |
|---|---|
| Basic while | while condition: |
| Infinite loop | while True: (needs break) |
| Exit loop | break |
| Skip iteration | continue |
| Else (no break) | for ... : ... else: ... |
| Retry pattern | while attempts < max: ... attempts += 1 |