Python lets you attach an else block to a for or while loop. The block runs only when the loop finishes its work without ever hitting a break. The name is famously misleading, so this lesson walks through what it really does, when it earns its keep, and when you should reach for a plain flag variable instead.
for ... else and while ... elseThe else clause sits at the same indentation level as the loop keyword, after the loop body finishes. It looks like the else of an if statement, but the rule is completely different.
Here is the for form:
The loop walks through every item in the cart, then the else block runs once at the end. Nothing dramatic. The else is just code that runs after the loop completes.
The while form looks the same:
The loop runs until stock becomes 0, the condition fails, and then the else runs once.
So far this looks pointless. Why bolt an else onto a loop when you could just put the same code on the next line? The answer only becomes interesting when break enters the picture.
else Actually MeansHere is the rule, written as plainly as possible: the `else` block runs when the loop completes normally without hitting `break`.
If the loop reaches its natural end (the iterable runs out, or the while condition becomes false), the else runs. If the loop is exited early by break, the else is skipped.
The else line did not print. The loop hit break on the second item, so the "walked the whole cart" message was skipped. Compare that with the same loop where nothing matches:
This time break never fires, the loop runs to completion, and the else block prints. That is the only behavioral difference, and it is the entire point of loop else.
A flowchart makes the two paths easy to see:
The else lives on the "iterable exhausted" path, not the break path. Every other way of leaving the loop, including return from the surrounding function, or an exception bubbling up, also skips the else. Only "the loop ran out of work to do" triggers it.
The keyword else is a bad name for this feature. With an if statement, else means "the condition was false". On a loop, else means something completely unrelated: "the loop completed without break". Many Python developers, including Guido van Rossum (Python's creator), have publicly said the keyword should have been nobreak instead.
Until you internalize the rule, mentally translate the keyword while reading. When you see this:
Read it in your head as:
That single substitution makes every loop-else clause stop being confusing. The block runs when the loop finished naturally, which means no break was triggered along the way.
Python also has a different else clause that attaches to try blocks, where it means "no exception was raised". Don't conflate the two; they happen to share a keyword and nothing else.
else Earns Its KeepThe one place loop else is genuinely useful is the search pattern: scanning a collection for an item, doing something with it if found, and running a "not found" handler if you reach the end empty-handed.
Imagine the cart contains a product that has gone out of stock. We want to find it, warn the customer, and stop scanning. If no out-of-stock item is in the cart, we want to print a clean confirmation.
The loop finds the out-of-stock item, prints the warning, and breaks. Because break fired, the else is skipped. Now run the same loop with an in-stock cart:
This time nothing matched. The loop ran to the end without break, so the else ran and printed the all-clear message. That is the canonical use case for loop else: a search that has both a "found" branch (inside the loop, with a break) and a "not found" branch (the else).
The search pattern has a particular shape, and once you spot it, loop else reads naturally:
break.else block holds the "didn't find anything" work.Notice how this avoids any extra state. There is no flag variable to track, no boolean to flip, no separate if after the loop. The control flow itself encodes the result.
else: A Flag VariableMost beginners write the search pattern with a flag. It works, and it is more obvious to anyone who has not learned about loop else yet. Here is the same out-of-stock check using a found flag:
This works correctly. It just carries more weight: a found = False line before the loop, a found = True line inside the loop, and a separate if not found: check after. Three pieces of bookkeeping for one piece of logic.
The loop-else version drops all three:
Same behavior, less state to track. The control flow alone tells you what happened, which is the appeal once you have internalized the "no-break" rule.
That said, the flag version has one real advantage: any Python reader understands it instantly, even if they have never seen loop else. The else version requires the reader to know the rule. That is the entire reason this feature is divisive, which we'll come back to in a moment.
A side-by-side comparison:
| Aspect | Loop else version | Flag variable version |
|---|---|---|
| Lines of code | Fewer (no flag, no post-loop if) | More (3 extra pieces) |
| Extra state | None | One boolean variable |
| Reader familiarity | Requires knowing the rule | Obvious to any Python reader |
| Risk of bugs | Low once understood | Easy to forget to set the flag |
| Works inside nested loops | Each loop has its own else | One flag per condition needed |
Both approaches produce the same result. The choice is mostly about your team and your codebase.
while ... else WorksLoop else works the same way on while loops. The block runs when the loop's condition becomes false on its own, and is skipped if break exits early.
A common while use case: keep prompting the customer for an in-stock item, give up after a fixed number of tries, and treat "ran out of attempts" as the failure case.
The condition attempts > 0 becomes false after three tries, the loop ends naturally, and the else runs to print the give-up message. If target had been in the cart, break would fire and the else would be skipped.
The "no-break" mental model still holds. With while, "completed normally" means "the condition went false". With for, it means "the iterable ran out". Either way, no break triggered the exit.
else Is SkippedThe else block runs only when the loop completes by exhausting its work. Anything else that ends the loop early skips the else. The list of "anything else" is short but worth being explicit about:
break exits the loop. The else is skipped.return (from a function containing the loop) exits the loop and the function. The else is skipped.raise (an exception) propagates out of the loop. The else is skipped.Here is return skipping the else:
In the first call, return item fires when the function finds "USB Cable". The else is skipped because the loop did not complete naturally; the function exited early. In the second call, the loop runs through every item without returning, then the else runs and prints the message before returning None.
This is a common source of confusion. Beginners sometimes assume else runs after return because it appears textually after the loop body. It does not. return exits the loop the same way break does, and the else is skipped.
Cost: There is no runtime overhead from the else clause. Python compiles it as a plain block of code on the post-loop fall-through path, the same as if you wrote it on the line after the loop. The cost is purely cognitive, paid by future readers of the code.
The two mistakes below cover almost every bug people hit with loop else.
Mistake 1: Thinking `else` runs only when the loop body never executed.
This is the most common misreading of the keyword. People assume else mirrors the if/else pairing, where else is "the other branch". With loops, else is not "the loop did not run". It runs even when the loop body executed many times, as long as the loop reached the end without break.
The cart is empty, so the loop body never runs. The else still fires, because "the loop completed without break" is trivially true when there were zero iterations. Now compare:
The cart has two items, the loop runs both, and the else still fires. The only time it would not fire is if the loop body executed break. The keyword has nothing to do with whether the body ran.
Mistake 2: Expecting `else` to run after `return`.
This is easy to slip into:
The "No out-of-stock items found" message never prints, because return True fired before the loop completed. The else only runs on the natural-completion path, and return exits before that path is reached.
else At All?Loop else is one of the more divisive features in Python. The split is roughly:
else version is shorter, has no extra state, and reads cleanly once you know the rule.A reasonable middle position, and the one this lesson recommends:
else for the search pattern. That is the case it was designed for, and the readability win is real.else does not pair with a break, it is just code that runs after the loop. Put it on the next line where every reader will understand it.else, the flag-variable version is the safer choice. Code that needs a comment to explain the keyword is code that should probably use a clearer keyword.Some style guides discourage loop else outright for that reason. PEP 8 (Python's official style guide) does not ban it, but the Python community is split on whether it earns its place. Knowing the rule cold is mandatory for reading other people's code; using it in your own code is a judgment call.
10 quizzes