399

I've noticed the following code is legal in Python. My question is why? Is there a specific reason?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

Many beginners accidentally stumble on this syntax when they try to put an if/else block inside of a while or for loop, and don't indent the else properly. The solution is to make sure the else block lines up with the if, assuming that it was your intent to pair them. This question explains why it didn't cause a syntax error, and what the resulting code means. See also I'm getting an IndentationError. How do I fix it?, for the cases where there is a syntax error reported.

See also Why does python use 'else' after for and while loops? for questions about how to make good use of the feature.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Ivan
  • 28,999
  • 6
  • 24
  • 21
  • 13
    @detly: That's because most people avoid this construct. :) I believe Guido mentioned during the Py3k process that, at the very least, the choice of the word `else` for this use had been a remarkably bad idea, and that they wouldn't be doing any more of these. – Nicholas Knight Jul 21 '10 at 08:26
  • 6
    @Nicholas Knight - yeah, tempting though it is, it'd probably be something only I understood on first glance. Any other poor sap would have to go and look at the language spec, or go back in time and post a question here on Sta- heeeeey... – detly Jul 21 '10 at 08:43
  • 1
    @detly What would be a better word than else? – Baz Sep 20 '13 at 13:17
  • 1
    @Baz - Nothing really, I just don't think the binary implication of "else" suits a looping construct very well. – detly Sep 20 '13 at 16:11
  • 9
    The idea behind choosing 'else' is that this construct is supposedly often used in conjunction with an 'if X: break' inside the while loop. Since the 'else' clause is executed if we don't break out of the loop, it forms a kinda-sorta 'else' to the 'if'. – Jonathan Hartley Nov 22 '13 at 10:25
  • 1
    I stumbled upon this a few minutes ago, [this is what I gathered](http://pastebin.com/HHMRpcQw). – Braden Best Feb 07 '15 at 17:00
  • 20
    They should rename it `after:`. – naught101 Mar 14 '16 at 22:42
  • 6
    @naught101 - After isn't really appropriate either, because it wouldn't execute if you used "break" or "return" to exit the loop. I always tell people who are struggling to remember the usage, "If you're breaking out of the loop, you have an opportunity to do something right before your break statement. If you're exhausting your collection (in a for loop) or breaking your loop condition (in a while loop), the 'else' clause is your place to wrap up." – AusIV Jun 20 '16 at 16:17
  • 1
    Hard to name, but if I heard correctly, Raymond Hettinger suggested `nobreak:` as a name here (BTW, this also works in `for` loops). – Tomasz Gandor Dec 11 '17 at 13:57
  • 3
    Possible duplicate of [Why does python use 'else' after for and while loops?](https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops) – pirho Apr 12 '18 at 10:44

13 Answers13

477

The else clause is only executed when your while condition becomes false. If you break out of the loop, or if an exception is raised, it won't be executed.

One way to think about it is as an if/else construct with respect to the condition:

if condition:
    handle_true()
else:
    handle_false()

is analogous to the looping construct:

while condition:
    handle_true()
else:
    # condition is false now, handle and go on with the rest of the program
    handle_false()

An example might be along the lines of:

while value < threshold:
    if not process_acceptable_value(value):
        # something went wrong, exit the loop; don't pass go, don't collect 200
        break
    value = update(value)
else:
    # value >= threshold; pass go, collect 200
    handle_threshold_reached()
ars
  • 120,335
  • 23
  • 147
  • 134
  • 73
    "The else clause is only executed when your while condition becomes false." The wording here implies that your while state goes from a state of true to false and than the else will be executed. However, if the while is never true, the else clause will still be executed. – user597608 Oct 10 '14 at 21:11
  • 2
    *pseudocode* So correct me if I'm wrong, but this is exactly the same as `while {} something` *except* that the `something` will be skipped if you `break` in the `while` loop. – Daniel Kaplan Mar 18 '15 at 21:48
  • 2
    Maybe the most precise pseudocode would be: while(True) { if (cond) { handle_true(); } else { handle_false(); break; } } – VinGarcia Dec 05 '16 at 14:46
  • 1
    the else clause is NOT executed even if the while condition becomes false, if the while loop is finished with 'break'. For example, changing the condition to false before break. – starriet Aug 05 '20 at 02:30
  • 1
    If `break` executes, then the condition never evaluated to false. (It's possible that the context became such that the condition *would* evaluated to false, if it were reached again, but that's not the same as evaluating to false.) – chepner Jan 22 '23 at 01:37
139

The else clause is executed if you exit a block normally, by hitting the loop condition or falling off the bottom of a try block. It is not executed if you break or return out of a block, or raise an exception. It works for not only while and for loops, but also try blocks.

You typically find it in places where normally you would exit a loop early, and running off the end of the loop is an unexpected/unusual occasion. For example, if you're looping through a list looking for a value:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 5
    Actually a fairly useful construct for such a thing. Don't know how many times I've put `found_it=False` at the start of a loop, and then do an if check on `found_it` at the end – Cruncher Feb 19 '20 at 18:51
43

Allow me to give an example on why to use this else-clause. But:

  • my point is now better explained in Leo’s answer
  • I use a for- instead of a while-loop, but else works similar (executes unless break was encountered)
  • there are better ways to do this (e.g. wrapping it into a function or raising an exception)
Breaking out of multiple levels of looping

Here is how it works: the outer loop has a break at the end, so it would only be executed once. However, if the inner loop completes (finds no divisor), then it reaches the else statement and the outer break is never reached. This way, a break in the inner loop will break out of both loops, rather than just one.

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'
Robert Siemer
  • 32,405
  • 11
  • 84
  • 94
Mark
  • 18,730
  • 7
  • 107
  • 130
29

The else-clause is executed when the while-condition evaluates to false.

From the documentation:

The while statement is used for repeated execution as long as an expression is true:

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

This repeatedly tests the expression and, if it is true, executes the first suite; if the expression is false (which may be the first time it is tested) the suite of the else clause, if present, is executed and the loop terminates.

A break statement executed in the first suite terminates the loop without executing the else clause’s suite. A continue statement executed in the first suite skips the rest of the suite and goes back to testing the expression.

Community
  • 1
  • 1
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
25

The else clause is only executed when the while-condition becomes false.

Here are some examples:

Example 1: Initially the condition is false, so else-clause is executed.

i = 99999999

while i < 5:
    print(i)
    i += 1
else:
    print('this')

OUTPUT:

this

Example 2: The while-condition i < 5 never became false because i == 3 breaks the loop, so else-clause was not executed.

i = 0

while i < 5:
    print(i)
    if i == 3:
        break
    i += 1
else:
    print('this')

OUTPUT:

0
1
2
3

Example 3: The while-condition i < 5 became false when i was 5, so else-clause was executed.

i = 0

while i < 5:
    print(i)
    i += 1
else:
    print('this')

OUTPUT:

0
1
2
3
4
this
Saif
  • 2,530
  • 3
  • 27
  • 45
23

My answer will focus on WHEN we can use while/for-else.

At the first glance, it seems there is no different when using

while CONDITION:
    EXPRESSIONS
print 'ELSE'
print 'The next statement'

and

while CONDITION:
    EXPRESSIONS
else:
    print 'ELSE'
print 'The next statement'

Because the print 'ELSE' statement seems always executed in both cases (both when the while loop finished or not run).

Then, it's only different when the statement print 'ELSE' will not be executed. It's when there is a breakinside the code block under while

In [17]: i = 0

In [18]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
else:
    print 'ELSE'
print 'The next statement'
   ....:
0
1
2
The next statement

If differ to:

In [19]: i = 0

In [20]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
print 'ELSE'
print 'The next statement'
   ....:
0
1
2
ELSE
The next statement

return is not in this category, because it does the same effect for two above cases.

exception raise also does not cause difference, because when it raises, where the next code will be executed is in exception handler (except block), the code in else clause or right after the while clause will not be executed.

HVNSweeting
  • 2,859
  • 2
  • 35
  • 30
13

I know this is old question but...

As Raymond Hettinger said, it should be called while/no_break instead of while/else.
I find it easy to understeand if you look at this snippet.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
if n == 0:
    print n

Now instead of checking condition after while loop we can swap it with else and get rid of that check.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
else:  # read it as "no_break"
    print n

I always read it as while/no_break to understand the code and that syntax makes much more sense to me.

Iluvatar
  • 642
  • 7
  • 19
2

Else is executed if while loop did not break.

I kinda like to think of it with a 'runner' metaphor.

The "else" is like crossing the finish line, irrelevant of whether you started at the beginning or end of the track. "else" is only not executed if you break somewhere in between.

runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
    print("Runner at: ", runner_at)
    if runner_at == unlucky_sector:
        print("Runner fell and broke his foot. Will not reach finish.")
        break
    runner_at += 1
else:
    print("Runner has finished the race!") # Not executed if runner broke his foot.

Main use cases is using this breaking out of nested loops or if you want to run some statements only if loop didn't break somewhere (think of breaking being an unusual situation).

For example, the following is a mechanism on how to break out of an inner loop without using variables or try/catch:

for i in [1,2,3]:
    for j in ['a', 'unlucky', 'c']:
        print(i, j)
        if j == 'unlucky':
            break
    else: 
        continue  # Only executed if inner loop didn't break.
    break         # This is only reached if inner loop 'breaked' out since continue didn't run. 

print("Finished")
# 1 a
# 1 b
# Finished
Leo Ufimtsev
  • 6,240
  • 5
  • 40
  • 48
2
thing = 'hay'
while thing:
  if thing == 'needle':
    print('I found it!!')  # wrap up for break
    break
  thing = haystack.next()
else:
  print('I did not find it.')  # wrap up for no-break

The possibly unfortunately named else-clause is your place to wrap up from loop-exhaustion without break.

  • if there is nothing to do in that case, no else-clause is necessary
  • you break with return or raise → the entire code after the call or try is your no-break place instead
  • instead of else you could set a default before while (e.g. found = False)
    • but it invites bugs related to the handling of the default
    • an else-clause saves you from those bugs

If you use a multiple breaks with non-trivial wrap-up, you should use a simple assignment before break, an else-clause assignment for no-break, and an if-elif-else or match-case to avoid repeating non-trival break handling code.

Note: everything above also applies to for thing in haystack:

Robert Siemer
  • 32,405
  • 11
  • 84
  • 94
-1

The else: statement is executed when and only when the while loop no longer meets its condition (in your example, when n != 0 is false).

So the output would be this:

5
4
3
2
1
what the...
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • I know but this kind of while/else doesn't work in Java. I find it quite interesting when I figured out it works in Python. I was just curious and wanted to know the technical reason. – Ivan Jul 21 '10 at 02:57
  • 7
    @Ivan: It's not so much that it doesn't *work* in Java but that it doesn't *exist* in Java. It could be made to work, if someone cared to add it to the language. – Ignacio Vazquez-Abrams Jul 21 '10 at 07:52
  • 1
    No, while False: .. else .. still runs the else clause. It's more accurate to say: else is only not ran if loop is broken out of. – Leo Ufimtsev Jul 29 '19 at 04:11
  • The `else` part is also not ran if there is a `return` or an exception is raised. – John Dec 05 '21 at 02:20
-1

Suppose you've to search an element x in a single linked list

    def search(self, x):
        position = 1
        p =self.start
        while p is not None:
            if p.info == x:
                print(x, " is at position ", position)
                return True
            position += 1
            p = p.link
        else:
            print(x, "not found in list") 
            return False

So if while conditions fails else will execute, hope it helps!

Rahul Negi
  • 61
  • 2
  • 10
  • Omitting the `else:` clause of the `while` statement in this snippet doesn’t change the behavior of the code. – sleighty May 24 '21 at 02:48
  • @BrunoEly this code is a snippet of a single linked list program, so you need a whole code to run it accurately. – Rahul Negi May 25 '21 at 13:07
  • 3
    You miss my point. I'm trying to say an `else:` clause after a `while` block that has _no `break` statement_ is pointless-- it does not alter the behavior of the code. – sleighty May 27 '21 at 09:38
  • Yeah, I got it, IDK how I misinterpreted that time(my bad). even with a break statement else will not execute though. – Rahul Negi Jan 21 '23 at 12:17
-2

The better use of 'while: else:' construction in Python should be if no loop is executed in 'while' then the 'else' statement is executed. The way it works today doesn't make sense because you can use the code below with the same results...

n = 5
while n != 0:
    print n
    n -= 1
print "what the..."
Jean Ferri
  • 13
  • 2
  • 10
    No, the difference is that the `else` block will not be executed if you are leaving loop using `break` or `return` keyword. In your example, `print` will be executed also if loop has ended on `break` command. – notsurewhattodo Oct 21 '13 at 16:43
  • 4
    You describe how most people wish that the feature worked, not how it actually works! – dotancohen Feb 29 '16 at 09:42
-2

As far as I know the main reason for adding else to loops in any language is in cases when the iterator is not on in your control. Imagine the iterator is on a server and you just give it a signal to fetch the next 100 records of data. You want the loop to go on as long as the length of the data received is 100. If it is less, you need it to go one more times and then end it. There are many other situations where you have no control over the last iteration. Having the option to add an else in these cases makes everything much easier.

Mansour.M
  • 500
  • 4
  • 18
  • The only times the `else:` clause doesn’t run is when you break out of the loop, so this example doesn’t call for such a construct. I.e., whatever code would be inside the `else:` block may doesn’t need an `else:` statement (for this example). – sleighty May 24 '21 at 02:51