While Loops, break and continue
When you do not know how many passes you need, loop on a condition instead of a collection - and make sure something moves it toward false.
Overview
Start here
Use a for loop when you know what you are walking through, and a while loop when you do not - when the number of passes depends on something that happens as you go. The condition is tested before each pass, so a while loop whose condition starts false never runs at all.
Loop while something stays true
The condition is checked before every pass. Something in the body has to change it, or the loop never ends.
Leaving early and skipping a pass
break exits the loop entirely. continue jumps to the next pass.
Staying out of infinite loops
while loop needs three things: a starting value, a condition, and something in the body that moves toward making the condition false.break leaves the loop immediately; the lines after it in the body are skipped, and so is every remaining pass.continue abandons only the current pass. The loop carries on with the next item.While Loops, break and continue: A Practical Guide
Loop on a condition, and know how to get out.
Repeating until something changes
A for loop runs a known number of times — once per item. A while loop runs until a condition stops being true, and how many times that is may not be knowable in advance.
balance = 1000
years = 0
while balance < 2000: # until it doubles, however long that takes
balance *= 1.05
years += 1
print(years) # 15That is the distinction in one line: for when you know the collection, while when you know the stopping condition.
Typical while situations: reading until end of input, retrying until success, simulating until convergence, running a menu until the user quits, polling until a job finishes.
Every while loop needs three things, and missing any one of them is the source of most bugs:
- Something initialised before the loop.
- A condition that can eventually become false.
- Something inside the loop that changes what the condition tests.
Infinite loops, deliberate and otherwise
Forget step three and the loop never ends:
count = 0
while count < 5:
print(count) # count never changes - runs for everThe deliberate version is a common and perfectly good pattern, especially for menus and servers:
while True:
command = input("> ")
if command == "quit":
break
handle(command)while True with a break is clearer than contorting the condition to cover every exit, and experienced Python programmers use it freely.
For loops that must not run for ever — anything involving a network, a file, or user input — add a safety counter:
attempts = 0
while not connected and attempts < 5:
connected = try_connect()
attempts += 1If you interrupt a runaway loop, Ctrl+C is the answer; the KeyboardInterrupt it raises is a normal Python exception.
break, continue and else
while True:
line = read_line()
if line is None:
break # leave the loop
if line.startswith("#"):
continue # skip to the next iteration
process(line)while also supports the else clause, which runs when the loop ends because its condition became false — not when it ended with break:
attempts = 0
while attempts < 3:
if try_login():
break
attempts += 1
else:
lock_account() # only if all three attempts failedWithout else, that needs a flag variable and an if after the loop.
Experiments to try
- Run the first editor. The countdown prints three times, then liftoff. The doubling loop stops at 128 - the first power of two past 100.
- Cause an infinite loop on purpose. Delete
count = count - 1and run. After ten seconds you get Execution timed out instead of a frozen page. Put the line back. - Run the second editor. The break loop stops before printing 4; the continue loop prints only the odd numbers.
- Swap them. Change
breaktocontinuein the first loop and predict the output before running - it should now skip 4 and carry on to 5 and 6.
Where that leaves you
A while loop repeats as long as its condition is true, so the body must move that condition toward false or the loop never ends. break leaves the loop entirely and continue skips just the current pass. Both work in for loops too.
A worked example: the retry loop
Retrying with a growing delay is the most common real use of while in production code, and it shows every part working together:
import time
max_attempts = 5
attempt = 0
delay = 1
while attempt < max_attempts:
try:
result = call_api()
break # success: stop retrying
except TimeoutError:
attempt += 1
if attempt == max_attempts:
raise # give up, loudly
time.sleep(delay)
delay *= 2 # exponential backoffFour decisions are visible in those lines, and each is deliberate: there is a maximum, so it cannot loop for ever; the delay grows, so a struggling service is not hammered; success breaks out immediately; and the final failure re-raises rather than returning None, so the caller knows.
Choosing between while and for
| Situation | Use |
|---|---|
| Every item in a collection | for |
| A known number of repeats | for ... in range(n) |
| Until a condition changes | while |
| Until the user quits | while True with break |
| Reading until end of file | for line in file — the file is iterable |
| Retrying with a limit | while with a counter |
The rule of thumb: if you find yourself managing an index by hand inside a while, a for loop probably fits better.
Common mistakes
- Forgetting to update the condition variable, producing an infinite loop.
- Updating it in only one branch, so a particular path loops for ever — the version of the bug that survives testing.
- Off-by-one conditions.
while i <= len(items)reads one past the end;<is almost always the correct comparison. - Using
whilewhereforfits, then having to manage the index by hand. - No maximum on a retry loop, so a failing dependency turns into a hang rather than an error.
- Modifying the collection being scanned inside the loop, so the condition never settles.
Loops that stop when they are close enough
A whole family of while loops has no counter at all: they repeat until a value settles.
target, guess, steps = 2.0, 1.0, 0
while abs(guess * guess - target) > 1e-12:
guess = (guess + target / guess) / 2
steps += 1
print(steps, round(guess, 10))5 1.4142135624That is Newton's method for a square root, and five passes get it to twelve decimal places. A for loop cannot express this well, because the number of repeats is a property of the answer rather than something known in advance.
The important detail is the comparison. It tests whether the result is *close enough*, not whether it is exact, and with floating point that distinction is not optional — while guess * guess != target may never become false, because the exact value is not representable and the loop would spin for ever on a difference of one bit.
Any convergence loop wants two things beyond the condition: a tolerance chosen deliberately rather than copied, and a maximum number of passes. Data that does not converge is not a hypothetical; a bad input, a sign error or an ill-conditioned problem all produce a loop that never settles, and without a cap that is a hung program rather than an error.
The condition is tested at the top
while checks before each pass, including the first, and two consequences follow that catch people out.
A loop can run zero times. If the condition starts false, the body never executes at all. That is usually what you want — a queue that is already empty needs no processing — but it means any variable the body was supposed to set must be given a value before the loop, or the code after it reads something that does not exist.
There is no do-while. Python has no form that runs the body first and tests afterwards. When you need one — prompting for input, where the first attempt must always happen — the idiom is to invert it:
while True:
answer = input("continue? ")
if answer in ("y", "n"):
breakThe test moves to the bottom as an if with a break, which is exactly what a do-while does and is more explicit about where the exit is. Trying to avoid it by initialising a variable to a fake value so that the condition passes the first time works and reads worse, because a reader has to work out that the initial value is a placeholder rather than data.
Where while loops genuinely belong
The situations are narrower than they first appear, because for covers more than beginners expect — files, generators, ranges and every collection. What is left is worth naming.
Consuming something that shrinks. Processing a work queue where handling one item can add more: while queue: with pop() inside. A for over the queue cannot cope with it growing during iteration.
Waiting on the outside world. Polling a job, retrying a request, reading until a connection closes. The number of passes depends on something you do not control, which is the definition of the case while exists for.
Driving a state machine. A loop whose body decides what the next state is and whose condition is "not finished yet" — parsers, games, menus, simulations. The state changes, the condition consults it, and neither is a count.
Consuming input by hand. Reading tokens one at a time where how many you take depends on what you just read.
The common thread is that the stopping point is discovered rather than known. When you can name the collection in advance, for is both shorter and safer, because it cannot fail to terminate.
Reading one someone else wrote
An unfamiliar while loop is worth three specific questions, in order, and they resolve most confusion faster than reading the body straight through.
What makes the condition false? Find the variable in the while line, then find every place the body assigns to it. If there is no such place, the loop depends on a break and the condition is decoration. If there are several, the loop has several ways to end and each is a separate path.
What has to be true before the first pass? The condition is tested immediately, so anything it reads must already exist and hold a sensible value. A loop that reads a variable initialised far above it is where an accidental zero-pass or infinite loop usually hides.
What is true after it ends? This is the question people skip, and it is the one that matters to the code below. A loop that ended because its condition turned false leaves different state than one that ended with break, and the lines afterwards frequently assume only one of the two. If the difference matters, while ... else distinguishes them explicitly instead of leaving the next reader to work it out.
Questions people ask
How do I stop an infinite loop? Ctrl+C in the terminal. In a notebook, interrupt the kernel.
Is while True bad practice? No — with a clear break it is often the clearest way to express "loop until something happens".
Can I use else with while? Yes, and it runs only when the loop exits because the condition became false, not after a break.
Does Python have a do-while loop? Not as syntax. The equivalent is while True: with the condition tested at the end and a break.
Why does my loop run one time too many? Usually <= where < was meant, or the counter being incremented after the check rather than before.
Is while slower than for? Slightly, because the condition is evaluated in Python each pass. It rarely matters; clarity should decide.
Making the exit obvious
A while loop has one job a for loop does not: it has to end, and a reader has to be able to see how. Three habits make that visible.
Put the exit condition where it is easiest to find. Either in the while line, or as a single early break near the top of the body. A loop with four break statements scattered through it has four exits, and working out which one fired is a debugging session rather than a reading.
Change the condition variable in one place. If the counter is incremented in three branches, one of them will eventually be missed, and the resulting infinite loop happens only on the path nobody tested. Updating it once at the top or bottom of the body is worth some duplication elsewhere.
Bound anything that waits. A loop that polls, retries, or reads from a network needs a maximum, and the maximum should be a named constant rather than a literal buried in the condition. Without it, a dependency that never responds turns into a program that never returns — which presents as a hang, with no error, no traceback and nothing in the logs.
The underlying point is that a for loop is guaranteed to terminate because the collection is finite, and a while loop carries no such guarantee. That guarantee is the thing you gave up, and these habits are how you replace it.
Can I loop while a file has more lines? You can, and for line in file already does exactly that without a condition to maintain.
Does break work inside a try? Yes, and any finally block runs before the loop is left.
Recap in one screen
foriterates a collection;whilerepeats until a condition turns false.- Every
whileneeds an initial value, a condition that can end, and an update inside the body. while Truewith abreakis idiomatic for menus, servers and retry loops.breakexits,continueskips, andelseruns only when nobreakoccurred.- Anything that waits on the outside world needs a maximum attempt count.