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..."
else
for this use had been a remarkably bad idea, and that they wouldn't be doing any more of these.
after:
.
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()
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. :-("
found_it=False
at the start of a loop, and then do an if check on found_it
at the end
In reply to Is there a specific reason?
, here is one interesting application: 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!'
For both while
and for
loops, the else
statement is executed at the end, unless break
was used.
In most cases there are better ways to do this (wrapping it into a function or raising an exception), but this works!
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.
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 break
inside 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.
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
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.
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...
else
part is also not ran if there is a return
or an exception is raised.
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
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!
else:
clause of the while
statement in this snippet doesn’t change the behavior of the code.
else:
clause after a while
block that has no break
statement is pointless-- it does not alter the behavior of the code.
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..."
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.
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.
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).
Success story sharing
while {} something
except that thesomething
will be skipped if youbreak
in thewhile
loop.