While loops, break, and the loop that never ends
Two loops, two different questions
for is for "do this once for each of these". while is for "keep going until something is true", when you do not know in advance how many times that is.
attempts = 0
while attempts < 3:
answer = input("Password: ")
if answer == "open":
print("welcome")
break
attempts += 1
else:
print("locked out")Everything interesting in loops is in that example.
The condition is checked before each pass
Including the first. A while whose condition is false at the start runs zero times. If you need the body to run at least once, Python has no do...while; the standard shape is:
while True:
value = input("Command: ")
if value:
breakbreak and continue
break leaves the loop immediately. continue skips the rest of this pass and goes back to the condition.
for line in lines:
if not line.strip():
continue # skip blank lines
if line.startswith("END"):
break # stop reading entirely
process(line)Both apply to the innermost loop only. There is no break 2 in Python. To leave two nested loops, put them in a function and return, or set a flag and check it — the function is almost always cleaner.
The else on a loop
That else in the first example is not attached to the if. A loop can have an else, and it runs when the loop finished without hitting break. It reads badly — nobreak would have been a better keyword — but it removes a flag variable:
for user in users:
if user.email == wanted:
print("found")
break
else:
print("no such user")Without it you would set found = False, set it true inside, and test it afterwards. Read else on a loop as "if we got all the way through".
Infinite loops, and getting out
n = 10
while n > 0:
print(n)
# forgot n -= 1This prints forever. Press Ctrl-C to stop it; that sends an interrupt and Python raises KeyboardInterrupt. In a notebook, use the stop button.
The rule that prevents most of these: whatever the condition tests, the body must change. Look at the condition, find the variable in it, and confirm the body modifies that variable on every path. Loops where the update is inside an if are the ones that hang.
The second common cause is a condition that can never become false — while len(queue) > 0 in a loop that appends more work than it removes.
The retry loop
This shape will come back when the course reaches API calls, and it is worth learning now:
import time
for attempt in range(1, 4):
result = try_request()
if result is not None:
break
wait = 2 ** attempt
print(f"attempt {attempt} failed, retrying in {wait}s")
time.sleep(wait)
else:
raise RuntimeError("all 3 attempts failed")A bounded for rather than a while gives you a guaranteed exit and a counter for free. The doubling wait is exponential backoff; module seven explains why it matters to the server you are calling.
Notice what this does not do: retry forever. A retry loop with no limit turns a temporary outage into an infinite one and hides the failure from whoever needs to know about it.
Reading until the data runs out
total = 0
while True:
entry = input("Amount (blank to finish): ").strip()
if not entry:
break
total += float(entry)
print(f"total {total:.2f}")The sentinel — the blank line that means stop — is a classic pattern for interactive input and for reading a stream where you cannot know the length ahead of time.
while and user input
A while around input() is how a small tool stays usable: it lets a person correct a typo instead of restarting the program.
while True:
raw = input("How many? ")
if raw.isdigit():
count = int(raw)
break
print("Digits only, please.")The validation and the loop belong together. A program that reads once, crashes on bad input, and asks the user to run it again is doing the work of a loop by hand.
When a while is the wrong tool
If you find yourself writing:
i = 0
while i < len(items):
print(items[i])
i += 1use for item in items:. It is shorter, it cannot go out of range, and it cannot forget the increment. If you genuinely need the position, for i, item in enumerate(items): gives both. Manual index management in Python is nearly always a habit carried over from another language, and it is where off-by-one errors come from.
The one thing to keep
A `while` loop hangs when the body does not change the variable its condition tests, and a loop's `else` runs only when no `break` was hit.
Before you move on
A worker loop is `while jobs:` and inside it pops one job, processes it, and appends any follow-up jobs it discovers. In production it never finishes even though each job completes in milliseconds. What is the most likely mechanism?
Pick the one you would defend. Nobody sees your answer.