if statement – Why does python use ‘else’ after for and while loops?

The Question :

535 people think this question is useful

I understand how this construct works:

for i in range(10):

    if i == 9:
        print("Too big - I'm giving up!")
    print("Completed successfully")

But I don’t understand why else is used as the keyword here, since it suggests the code in question only runs if the for block does not complete, which is the opposite of what it does! No matter how I think about it, my brain can’t progress seamlessly from the for statement to the else block. To me, continue or continuewith would make more sense (and I’m trying to train myself to read it as such).

I’m wondering how Python coders read this construct in their head (or aloud, if you like). Perhaps I’m missing something that would make such code blocks more easily decipherable?

The Question Comments :
  • You might like to translate it to “then” in your head.
  • Don’t forget the key line in the Zen of Python: “… that way may not be obvious at first unless you’re Dutch.”
  • In my head I translate it into “if not break”. And, since break is used a lot in “I’ve found it” loops, you can translate it to “if not found”, which is not far from what else reads
  • I think the real question many people have here is “What’s the difference between for ... else foo() and just putting foo() after the for loop?” And the answer is that they behave differently only if the loop contains a break (as described in detail below).
  • A semicolon in python… my eyes hurt.. even though it is syntactically correct it is not good practice to do so

The Answer 1

316 people think this answer is useful

It’s a strange construct even to seasoned Python coders. When used in conjunction with for-loops it basically means “find some item in the iterable, else if none was found do …”. As in:

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
    print('No object found.')

But anytime you see this construct, a better alternative is to either encapsulate the search in a function:

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

Or use a list comprehension:

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
    print('No object found.')

It is not semantically equivalent to the other two versions, but works good enough in non-performance critical code where it doesn’t matter whether you iterate the whole list or not. Others may disagree, but I personally would avoid ever using the for-else or while-else blocks in production code.

See also [Python-ideas] Summary of for…else threads

The Answer 2

657 people think this answer is useful

A common construct is to run a loop until something is found and then to break out of the loop. The problem is that if I break out of the loop or the loop ends I need to determine which case happened. One method is to create a flag or store variable that will let me do a second test to see how the loop was exited.

For example assume that I need to search through a list and process each item until a flag item is found and then stop processing. If the flag item is missing then an exception needs to be raised.

Using the Python forelse construct you have

for i in mylist:
    if i == theflag:
    raise ValueError("List argument missing terminal flag.")

Compare this to a method that does not use this syntactic sugar:

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

In the first case the raise is bound tightly to the for loop it works with. In the second the binding is not as strong and errors may be introduced during maintenance.

The Answer 3

187 people think this answer is useful

There’s an excellent presentation by Raymond Hettinger, titled Transforming Code into Beautiful, Idiomatic Python, in which he briefly addresses the history of the for ... else construct. The relevant section is “Distinguishing multiple exit points in loops” starting at 15:50 and continuing for about three minutes. Here are the high points:

  • The for ... else construct was devised by Donald Knuth as a replacement for certain GOTO use cases;
  • Reusing the else keyword made sense because “it’s what Knuth used, and people knew, at that time, all [for statements] had embedded an if and GOTO underneath, and they expected the else;”
  • In hindsight, it should have been called “no break” (or possibly “nobreak”), and then it wouldn’t be confusing.*

So, if the question is, “Why don’t they change this keyword?” then Cat Plus Plus probably gave the most accurate answer – at this point, it would be too destructive to existing code to be practical. But if the question you’re really asking is why else was reused in the first place, well, apparently it seemed like a good idea at the time.

Personally, I like the compromise of commenting # no break in-line wherever the else could be mistaken, at a glance, as belonging inside the loop. It’s reasonably clear and concise. This option gets a brief mention in the summary that Bjorn linked at the end of his answer:

For completeness, I should mention that with a slight change in syntax, programmers who want this syntax can have it right now:

for item in sequence:
else:  # no break

* Bonus quote from that part of the video: “Just like if we called lambda makefunction, nobody would ask, ‘What does lambda do?'”

The Answer 4

44 people think this answer is useful

To make it simple, you can think of it like that;

  • If it encounters the break command in the for loop, the else part will not be called.
  • If it does not encounter the break command in the for loop, the else part will be called.

In other words, if for loop iteration is not “broken” with break, the else part will be called.

The Answer 5

36 people think this answer is useful

Because they didn’t want to introduce a new keyword to the language. Each one steals an identifier and causes backwards compatibility problems, so it’s usually a last resort.

The Answer 6

19 people think this answer is useful

I think documentation has a great explanation of else, continue

[…] it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement.”

Source: Python 2 docs: Tutorial on control flow

The Answer 7

18 people think this answer is useful

The easiest way I found to ‘get’ what the for/else did, and more importantly, when to use it, was to concentrate on where the break statement jumps to. The For/else construct is a single block. The break jumps out of the block, and so jumps ‘over’ the else clause. If the contents of the else clause simply followed the for clause, it would never be jumped over, and so the equivalent logic would have to be provided by putting it in an if. This has been said before, but not quite in these words, so it may help somebody else. Try running the following code fragment. I’m wholeheartedly in favour of the ‘no break’ comment for clarity.

for a in range(3):
    if a==4: # change value to force break or not
else: #no break  +10 for whoever thought of this decoration
    print('for completed OK')

print('statement after for loop')

The Answer 8

15 people think this answer is useful

I read it something like:

If still on the conditions to run the loop, do stuff, else do something else.

The Answer 9

14 people think this answer is useful

Since the technical part has been pretty much answered, my comment is just in relation with the confusion that produce this recycled keyword.

Being Python a very eloquent programming language, the misuse of a keyword is more notorious. The else keyword perfectly describes part of the flow of a decision tree, “if you can’t do this, (else) do that”. It’s implied in our own language.

Instead, using this keyword with while and for statements creates confusion. The reason, our career as programmers has taught us that the else statement resides within a decision tree; its logical scope, a wrapper that conditionally return a path to follow. Meanwhile, loop statements have a figurative explicit goal to reach something. The goal is met after continuous iterations of a process.

if / else indicate a path to follow. Loops follow a path until the “goal” is completed.

The issue is that else is a word that clearly define the last option in a condition. The semantics of the word are both shared by Python and Human Language. But the else word in Human Language is never used to indicate the actions someone or something will take after something is completed. It will be used if, in the process of completing it, an issue rises (more like a break statement).

At the end, the keyword will remain in Python. It’s clear it was mistake, clearer when every programmer tries to come up with a story to understand its usage like some mnemonic device. I’d have loved if they have chosen instead the keyword then. I believe that this keyword fits perfectly in that iterative flow, the payoff after the loop.

It resembles that situation that some child has after following every step in assembling a toy: And THEN what Dad?

The Answer 10

7 people think this answer is useful

I read it like “When the iterable is exhausted completely, and the execution is about to proceed to the next statement after finishing the for, the else clause will be executed.” Thus, when the iteration is broken by break, this will not be executed.

The Answer 11

7 people think this answer is useful

Great answers are:

  • this which explain the history, and
  • this gives the right citation to ease yours translation/understanding.

My note here comes from what Donald Knuth once said (sorry can’t find reference) that there is a construct where while-else is indistinguishable from if-else, namely (in Python):

x = 2
while x > 3:

has the same flow (excluding low level differences) as:

x = 2
if x > 3:

The point is that if-else can be considered as syntactic sugar for while-else which has implicit break at the end of its if block. The opposite implication, that while loop is extension to if, is more common (it’s just repeated/looped conditional check), because if is often taught before while. However that isn’t true because that would mean else block in while-else would be executed each time when condition is false.

To ease your understanding think of it that way:

Without break, return, etc., loop ends only when condition is no longer true and in such case else block will also execute once. In case of Python for you must consider C-style for loops (with conditions) or translate them to while.

Another note:

Premature break, return, etc. inside loop makes impossible for condition to become false because execution jumped out of the loop while condition was true and it would never come back to check it again.

The Answer 12

6 people think this answer is useful

I agree, it’s more like an ‘elif not [condition(s) raising break]’.

I know this is an old thread, but I am looking into the same question right now, and I’m not sure anyone has captured the answer to this question in the way I understand it.

For me, there are three ways of “reading” the else in For... else or While... else statements, all of which are equivalent, are:

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (presumably there is such a condition, or you wouldn’t have a loop)

So, essentially, the “else” in a loop is really an “elif …” where ‘…’ is (1) no break, which is equivalent to (2) NOT [condition(s) raising break].

I think the key is that the else is pointless without the ‘break’, so a for...else includes:

    do stuff
    conditional break # implied by else
else not break:
    do more stuff

So, essential elements of a for...else loop are as follows, and you would read them in plainer English as:

    do stuff
else: # read as "else not break" or "else not condition"
    do more stuff

As the other posters have said, a break is generally raised when you are able to locate what your loop is looking for, so the else: becomes “what to do if target item not located”.


You can also use exception handling, breaks, and for loops all together.

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
    print("X loop complete without error")


x: 0
x: 1
x: 2
# loop not completed (hit break), so else didn't run


Simple example with a break being hit.

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
else: # not executed because break is hit
    print("y_loop completed without break----------\n")


y: 0
y: 1
y: 2
BREAK: y is 2
# loop not completed (hit break), so else didn't run


Simple example where there no break, no condition raising a break, and no error are encountered.

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
     print("z_loop complete without break or error\n----------\n")


z: 0
z: 1
z: 2
z_loop complete without break or error

The Answer 13

6 people think this answer is useful

The else keyword can be confusing here, and as many people have pointed out, something like nobreak, notbreak is more appropriate.

In order to understand for ... else ... logically, compare it with try...except...else, not if...else..., most of python programmers are familiar with the following code:

    print("Error happened.") # The try block threw an exception
    print("Everything is find.") # The try block does things just find.

Similarly, think of break as a special kind of Exception:

for x in iterable:
except break:
    pass # Implied by Python's loop semantics
    print('no break encountered')  # No break statement was encountered

The difference is python implies except break and you can not write it out, so it becomes:

for x in iterable:
    print('no break encountered')  # No break statement was encountered

Yes, I know this comparison can be difficult and tiresome, but it does clarify the confusion.

The Answer 14

5 people think this answer is useful

Codes in else statement block will be executed when the for loop was not be broke.

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
    print 'can not find 5!'
#can not find 5!

From the docs: break and continue Statements, and else Clauses on Loops

Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement. This is exemplified by the following loop, which searches for prime numbers:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(Yes, this is the correct code. Look closely: the else clause belongs to the for loop, not the if statement.)

When used with a loop, the else clause has more in common with the else clause of a try statement than it does that of if statements: a try statement’s else clause runs when no exception occurs, and a loop’s else clause runs when no break occurs. For more on the try statement and exceptions, see Handling Exceptions.

The continue statement, also borrowed from C, continues with the next iteration of the loop:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9

The Answer 15

5 people think this answer is useful

Here’s a way to think about it that I haven’t seen anyone else mention above:

First, remember that for-loops are basically just syntactic sugar around while-loops. For example, the loop

for item in sequence:

can be rewritten (approximately) as

item = None
while sequence.hasnext():
    item = sequence.next()

Second, remember that while-loops are basically just repeated if-blocks! You can always read a while-loop as “if this condition is true, execute the body, then come back and check again”.

So while/else makes perfect sense: It’s the exact same structure as if/else, with the added functionality of looping until the condition becomes false instead of just checking the condition once.

And then for/else makes perfect sense too: because all for-loops are just syntactic sugar on top of while-loops, you just need to figure out what the underlying while-loop’s implicit conditional is, and then the else corresponds to when that condition becomes False.

The Answer 16

3 people think this answer is useful
for i in range(3):

    if i == 2:
        print("Too big - I'm giving up!")
    print("Completed successfully")

“else” here is crazily simple, just mean

1, “if for clause is completed”

for i in range(3):

    if i == 2:
        print("Too big - I'm giving up!")
if "for clause is completed":
    print("Completed successfully")

It’s wielding to write such long statements as “for clause is completed”, so they introduce “else”.

else here is a if in its nature.

2, However, How about for clause is not run at all

In [331]: for i in range(0):
     ...:     print(i)
     ...:     if i == 9:
     ...:         print("Too big - I'm giving up!")
     ...:         break
     ...: else:
     ...:     print("Completed successfully")
Completed successfully

So it’s completely statement is logic combination:

if "for clause is completed" or "not run at all":
     do else stuff

or put it this way:

if "for clause is not partially run":
    do else stuff

or this way:

if "for clause not encounter a break":
    do else stuff

The Answer 17

2 people think this answer is useful

You could think of it like, else as in the rest of the stuff, or the other stuff, that wasn’t done in the loop.

The Answer 18

2 people think this answer is useful

Here’s another idiomatic use case besides searching. Let’s say you wanted to wait for a condition to be true, e.g. a port to be open on a remote server, along with some timeout. Then you could utilize a while...else construct like so:

import socket
import time

sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
    if sock.connect_ex(('', 80)) is 0:
        print('Port is open now!')
    print('Still waiting...')
    raise TimeoutError()

The Answer 19

2 people think this answer is useful

I was just trying to make sense of it again myself. I found that the following helps!

• Think of the else as being paired with the if inside the loop (instead of with the for) – if condition is met then break the loop, else do this – except it’s one else paired with multiple ifs!
• If no ifs were satisfied at all, then do the else.
• The multiple ifs can also actually be thought of as ifelifs!

The Answer 20

-2 people think this answer is useful

I consider the structure as for (if) A else B, and for(if)-else is a special if-else, roughly. It may help to understand else.

A and B is executed at most once, which is the same as if-else structure.

for(if) can be considered as a special if, which does a loop to try to meet the if condition. Once the if condition is met, A and break; Else, B.

The Answer 21

-3 people think this answer is useful

Python uses an else after for and while loops so that if nothing applies to the loop, something else happens. For example:

test = 3
while test == 4:

The output would be ‘Hi’ over and over again (if I’m correct).

Add a Comment