I understand how this construct works:
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break
else:
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?
This question is about the underlying design decision, i.e. why it is useful to be able to write this code. See also Else clause on Python while statement for the specific question about what the syntax means.
26 Answers 26
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 for
...else
construct you have
for i in mylist:
if i == theflag:
break
process(i)
else:
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
break
process(i)
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.
-
79I'd have to say this syntactic sugar might rot your project's teeth. This would not make a
Python: the good parts
book.boatcoder– boatcoder2015年02月01日 17:10:17 +00:00Commented Feb 1, 2015 at 17:10 -
7
process
will execute on eachi
that exists in the list beforetheflag
is reached, it will not be executed on elements in the list aftertheflag
, and it will not be executed ontheflag
.Lance Helsten– Lance Helsten2015年03月11日 14:31:10 +00:00Commented Mar 11, 2015 at 14:31 -
29the else statement also gets executed if the iterable has no elementsLost Crotchet– Lost Crotchet2019年05月01日 16:15:45 +00:00Commented May 1, 2019 at 16:15
-
9I think they made a mistake by calling it
else:
. It's really misleading. Before trying it, I was pretty sure it runs when there are no elements to iterate. More accurate name would have beenpassed:
,completed:
or something.Robo Robok– Robo Robok2020年09月10日 10:13:47 +00:00Commented Sep 10, 2020 at 10:13 -
6As for maintenance, put the "for-else" into an "if" block and see if your maintainers don't more than once out-dent the "else" to bind to the "if" thinking they are fixing a bug.Les– Les2021年03月10日 11:39:51 +00:00Commented Mar 10, 2021 at 11:39
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
break
else:
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]))
else:
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.
-
78The list comprehension is the wrong one-liner. If you're looking for a single item, as in the
for
loop examples, and want to use a generator expression / list comprehension, then you wantnext((o for o in objects if o.key == search_key), None)
or wrap it in atry
/except
and use no default value instead of anif
/else
.agf– agf2012年04月02日 16:33:31 +00:00Commented Apr 2, 2012 at 16:33 -
6and like Lance Helsten's answer, there are actual cases where it's better to use a
for/else
construct.andrean– andrean2014年03月11日 08:52:00 +00:00Commented Mar 11, 2014 at 8:52 -
8Cheers. I had a badly indented file where an
else
got paired with afor
and I had no idea that was legal.maxywb– maxywb2014年05月02日 22:01:57 +00:00Commented May 2, 2014 at 22:01 -
27It is worth mentioning that the else clause will run even if the for loop has values unless a
break
statement is explicity run as in this example. From the docs above: "Theelse
clause has another perceived problem: if there is nobreak
in the loop, theelse
clause is functionally redundant.". e.g.for x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
dhackner– dhackner2014年08月28日 01:20:44 +00:00Commented Aug 28, 2014 at 1:20 -
4I'm happy that I didn't read "find some item in the iterable, else if none was found do ..." before actually knowing how for-else works because this would horribly mislead me how for-else works.
else
executes when loop ends naturally (i.e. w/obreak
) and the "find" part is false for regular for-else loop w/oif
andbreak
statements which you added in your code.WloHu– WloHu2019年02月21日 15:58:11 +00:00Commented Feb 21, 2019 at 15:58
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 certainGOTO
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 anif
andGOTO
underneath, and they expected theelse
;" - 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: process(item) else: # no break suite
* Bonus quote from that part of the video: "Just like if we called lambda makefunction, nobody would ask, 'What does lambda do?'"
-
5Why not add support for nobreak next to else, have both be equal and exist alongside eachother and make a clear PEP style rule that nobreak should be used instead of else?jaaq– jaaq2020年10月28日 11:34:33 +00:00Commented Oct 28, 2020 at 11:34
-
6@jaaq I can't speak for Python core devs but consider the PEP 20 line "There should be one-- and preferably only one --obvious way to do it."Air– Air2020年11月16日 19:50:37 +00:00Commented Nov 16, 2020 at 19:50
-
5recent pep doc states that multiple ways is OK, just not multiple obvious ways. Since a
nobreak
keyword could be more obvious, maybe this is indeed a way to improve the syntax.jaaq– jaaq2020年12月09日 08:54:48 +00:00Commented Dec 9, 2020 at 8:54 -
7"nobreak" would be a new keyword, and, as a rule, language designers are very hesitant to add keywords to an existing language, because it insta-breaks all code that has used that identifier for something else.zwol– zwol2021年07月12日 22:00:42 +00:00Commented Jul 12, 2021 at 22:00
-
7The
# no break
comment seems like a really nice idea to me. Only seeingelse
can be very misleading, as in 99% of caseselse
is related to anif
, so adding a comment like that can be useful. That's what comments should be used for, after all - commenting non-obvious or potentially misleading stuff.at54321– at543212021年10月22日 15:04:34 +00:00Commented Oct 22, 2021 at 15:04
To make it simple, you can think of it like that;
- If it encounters the
break
command in thefor
loop, theelse
part will not be called. - If it does not encounter the
break
command in thefor
loop, theelse
part will be called.
In other words, if for loop iteration is not "broken" with break
, the else
part will be called.
-
4The
else
block will also not be executed if the body of the loop raises an exception.Amal K– Amal K2019年10月02日 15:50:40 +00:00Commented Oct 2, 2019 at 15:50 -
13And the else block will also be executed if the list is empty and the for loop does not iterate at all.Chiraz BenAbdelkader– Chiraz BenAbdelkader2020年07月05日 11:19:57 +00:00Commented Jul 5, 2020 at 11:19
-
6If like to read
for/else
asfor/nobreak
.timgeb– timgeb2022年02月17日 16:17:35 +00:00Commented Feb 17, 2022 at 16:17 -
3@Amal K the else still executes if the exception is handled with a try-exceptHarley– Harley2022年11月12日 01:23:45 +00:00Commented Nov 12, 2022 at 1:23
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.
-
5Seems like
finally
would have been a better choice in that case. Was the finally keyword not yet present at the time this construct was introduced?Ponkadoodle– Ponkadoodle2014年01月11日 23:01:39 +00:00Commented Jan 11, 2014 at 23:01 -
49@Wallacoloo
finally
isn't much better, because it implies the block would always be executed after the loop, and it isn't (because that'd be redundant with just putting the code to run after the loop).Cat Plus Plus– Cat Plus Plus2014年01月12日 01:43:44 +00:00Commented Jan 12, 2014 at 1:43 -
10
-
1
completed
would have been a better keyword here; to signify the that the for-loop's execution was not broken (irrespective of whether any loops were actually performed). At least then if someone accidentally shifts the indentation it wouldn't end up causing incorrect behaviour because theelse
has suddenly moved to anif
construct....Den-Jason– Den-Jason2020年09月07日 19:36:18 +00:00Commented Sep 7, 2020 at 19:36 -
1the best keyword would be something like
afterBreak
, but ofcourse a keyword should be one singular word, so not really sure what the keyword should be.Anm– Anm2023年10月19日 06:35:16 +00:00Commented Oct 19, 2023 at 6:35
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):
print(a)
if a==4: # change value to force break or not
break
else: #no break +10 for whoever thought of this decoration
print('for completed OK')
print('statement after for loop')
EDIT - I notice this question is still running
Second better thoughts ...
The 'no break' comment is a negative. It's so much easier to understand a positive assertion, and that is that the for
iterable was exhausted.
for a in range(3):
print(a)
if a==4: # change value to force break or not
print('ending for loop with a break')
break
else: # when iterable exhausted
print('ending for loop as iterable exhausted')
print('for loop ended one way or another')
That also reinforces this interpretation
if iterable_supplies_a_value:
run_the_for_with_that_value
else:
do_something_else
A place I've been using it recently is with a for
instead of a while True:
loop, when early debugging some recursive or search function. There's nothing more annoying than a silly error in the finish loop condition hanging the program, so I tend to use for _ in range(MAX_ITERATIONS):
instead, which leads to the following use ...
for _ in range(MAX_ITERATIONS):
do_stuff()
if end_condition:
break
else:
log('doh, messed up that break condition again!')
log('some maybe helpful debugging data')
-
2"The break jumps out of the block, and so jumps 'over' the else clause" - while this may be helpful as a way of "getting"
for:
/else:
, it doesn't really provide a justification for the keyword beingelse
. Given the framing given here,then:
seems like it would be much more natural. (There are reasons forelse
being chosen, given in other answers - they're just not provided here.)Mark Amery– Mark Amery2018年02月16日 12:10:20 +00:00Commented Feb 16, 2018 at 12:10 -
@Neil_UK "if iterable_supplies_a_value:" sounds like "else:" runs only when the iterable was empty, which is a common wrong guess of what it does. But previous parts of your answer explain it correctly. As written, it's unclear what you meant by "That also reinforces this interpretation"Beni Cherniavsky-Paskin– Beni Cherniavsky-Paskin2023年10月19日 08:30:59 +00:00Commented Oct 19, 2023 at 8:30
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."
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?
-
1I think that this answer addresses the issue of confusion I think the OP was talking about. The else keyword does exactly the opposite of what you would expect of from the English meaning of else when attached to the action of for. In theory, the for ... else could have worked differently in that you end up in the else part when the loop is broken out of, But the problem is that to use it to find element x, and handle the case where x is not found, you may have to use a flag or another test after the whole for .. else constructSpacen Jasset– Spacen Jasset2018年03月31日 13:14:30 +00:00Commented Mar 31, 2018 at 13:14
-
1My career as a programmer has taught me nothing of the sort. Even if I had had a career as a programmer, this would still be true.Jürgen A. Erhard– Jürgen A. Erhard2023年10月20日 18:44:49 +00:00Commented Oct 20, 2023 at 18:44
-
Your answer would be more credible if you used correct English. There's some irony in complaining about an (admittedly rare) item of Python syntax in English that contains multiple grammatical errors.PM 2Ring– PM 2Ring2024年08月14日 17:23:15 +00:00Commented Aug 14, 2024 at 17:23
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:
print("foo")
break
else:
print("boo")
has the same flow (excluding low level differences) as:
x = 2
if x > 3:
print("foo")
else:
print("boo")
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 caseelse
block will also execute once. In case of Pythonfor
you must consider C-stylefor
loops (with conditions) or translate them towhile
.
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.
I read it something like:
If still on the conditions to run the loop, do stuff, else do something else.
-
Your still on the conditions is helpful (+1) although it is wrong - it's human ;-)Wolf– Wolf2014年11月28日 10:06:42 +00:00Commented Nov 28, 2014 at 10:06
-
1-1; this pronunciation of
for:
/else:
makes it sound like theelse:
will always run after the loop, which isn't the case.Mark Amery– Mark Amery2018年02月16日 12:11:30 +00:00Commented Feb 16, 2018 at 12:11
I'm wondering how Python coders read this construct in their head (or aloud, if you like).
I simply think in my head:
"else no
break
was encountered..."
That's it!
This is because the else
clause executes only if a break
statement was NOT encountered in the for
loop.
Reference:
See here: https://book.pythontips.com/en/latest/for_-_else.html#else-clause (emphasis added, and "not" changed to "NOT"):
for
loops also have anelse
clause which most of us are unfamiliar with. Theelse
clause executes after the loop completes normally. This means that the loop did NOT encounter a break statement.
That being said, I recommend against using this unusual feature of the language. Don't use the else
clause after a for loop. It's confusing to most people, and just slows down their ability to read and understand the code.
-
1I could not convince myself that normal completion of a loop is through a
break
statement. For me it is otherwise. hence not using this weird overthought construct.Nik O'Lai– Nik O'Lai2023年05月05日 14:28:31 +00:00Commented May 5, 2023 at 14:28
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:
try:
do_something()
except:
print("Error happened.") # The try block threw an exception
else:
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:
do_something(x)
except break:
pass # Implied by Python's loop semantics
else:
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:
do_something(x)
else:
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.
-
2You should make a link to resource when you copy from it: Nick Coghlan's Python Notes.godaygo– godaygo2017年10月31日 14:05:02 +00:00Commented Oct 31, 2017 at 14:05
-
1@godaygo thanks for the link. I read and accept the concept when first learning python, didn't memorize the source when writing the answer.cizixs– cizixs2017年11月01日 03:56:59 +00:00Commented Nov 1, 2017 at 3:56
-
3@cizixs You "didn't memorise the source" but just happened to include entire sentences of comments identical to the original? Ooookaaaay.Mark Amery– Mark Amery2018年02月16日 12:19:22 +00:00Commented Feb 16, 2018 at 12:19
-
1I came here looking for this one, but.. isn't
try: stuff(); except: error(); else: ok()
really the same astry: stuff(); ok(); except: error()
?Phil– Phil2020年08月22日 11:00:38 +00:00Commented Aug 22, 2020 at 11:00 -
1@phil Not exactly, because if there's an exception raised inside
else
, it'll bubble up.user19513069– user195130692022年10月07日 16:48:25 +00:00Commented Oct 7, 2022 at 16:48
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.
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:
else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
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:
for:
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:
for:
do stuff
condition:
break
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".
Example
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:
try:
raise AssertionError("ASSERTION ERROR: x is {}".format(x))
except:
print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
break
else:
print("X loop complete without error")
Result
x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run
Example
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))
break
else: # not executed because break is hit
print("y_loop completed without break----------\n")
Result
y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run
Example
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))
break
if z == 4: # will not be executed
raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
print("z_loop complete without break or error\n----------\n")
Result
z: 0
z: 1
z: 2
z_loop complete without break or error
----------
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'
break
else:
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
-
1This adds nothing and doesn't answer the question, which is not how but why.Air– Air2017年01月23日 17:04:20 +00:00Commented Jan 23, 2017 at 17:04
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:
do_something(item)
can be rewritten (approximately) as
item = None
while sequence.hasnext():
item = sequence.next()
do_something(item)
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.
for i in range(3):
print(i)
if i == 2:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
"else" here is crazily simple, just mean
1, "if for clause
is completed"
for i in range(3):
print(i)
if i == 2:
print("Too big - I'm giving up!")
break;
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
-
else acts as "transaction" in SQL.Wizard– Wizard2018年08月25日 05:12:36 +00:00Commented Aug 25, 2018 at 5:12
It may seems confusing for programmers as we always expect to see if
when we face an else
, but in real life we use else
with for
As an example, I ask my son to search the bookshelf for dictionary and bring it to me, and if he can not find it then he should go and buy one for me
This is the algorithm
in his
mind
for book in bookshelf:
if book == 'dictionary':
#Lucky Me !! I find it lets bring it to dad
bring('dictionary')
break #and of course I break and stop searching
else: #too bad :( we do not have any dictionaries
buy('dictionary');
-
I think it doesn't make sense for the bring to be in the loop but the buy not. And the "if he can not find it" in his head does not appear as an if in the code. I think the better code for his mental algorithm is a direct translation. A loop to seek the book, then an if to either bring or buy it - as per answer stackoverflow.com/a/9980160/896451ChrisJJ– ChrisJJ2024年06月01日 16:10:37 +00:00Commented Jun 1, 2024 at 16:10
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(('127.0.0.1', 80)) is 0:
print('Port is open now!')
break
print('Still waiting...')
else:
raise TimeoutError()
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 if
s!
• If no if
s were satisfied at all, then do the else
.
• The multiple if
s can also actually be thought of as if
-elif
s!
-
there is no need for an if in the loop, and there's no need for a loop either - you can use else with try-except, for instancePhil– Phil2020年08月22日 11:04:04 +00:00Commented Aug 22, 2020 at 11:04
A loop's else branch executes once, regardless of whether the loop enters its body or not, unless the loop body is entered but does not finish. That is, inside the loop a break or return statement is encountered.
my_list = []
for i in my_list:
print(i, end=',')
else:
print('loop did not enter')
##################################
for i in range(1,6,1):
print(i, end=',')
else:
print('loop completed successfully:', i)
##################################
for i in range(1,6,1):
if i == 3:
print('loop did not finish:', i)
break
print(i, end=',')
else:
print('else:', i)
Output:
loop did not enter
1,2,3,4,5,loop completed successfully: 5
1,2,loop did not finish: 3
It's the same for while-else.
import random
random.seed(8)
i = 100
while i < 90:
print(i, end=',')
i = random.randint(0,100)
else:
print('loop did not enter:', i)
##################################
i = 25
while i < 90:
print(i, end=',')
i = random.randint(0,100)
else:
print('loop completed successfully:', i)
##################################
i = 25
while i < 90:
if i % 10 == 0:
print('loop did not finish:', i)
break
print(i, end=',')
i = random.randint(0,100)
else:
print('else:', i)
Output:
loop did not enter: 100
25,29,47,48,16,24,loop completed successfully: 90
25,5,loop did not finish: 10
The else clause executes after the loop completes normally. This means: The else block just after for/while is executed only when the loop is NOT terminated by a break statement
for item in lista:
if(obj == item ):
print("if True then break will run and else not run")
break;
else:
print("in else => obj not fount ")
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
break keyword is used to end the loop. if the i = 9 then the loop will end. while any if conditions did not much the satisfaction, then the else
will do the rest part.
Sometimes for me, it helps to better understand code when broken down into the building blocks. With that said, let's look at how the code branching might look in some rudimentary pseudo-assembler code..
Python:
for i in range(len(haystack)):
print("1")
if haystack[i] == needle:
break
else:
print("2")
print("3")
Pseudo-generated code:
i = 0
for:
GOTO else IF i >= LENGTH(haystack)
PRINT "1"
GOTO break IF haystack[i] == needle
i = i + 1
GOTO for
else:
PRINT "2"
break:
PRINT "3"
Simply put, the else
block will be executed if the loop exhausts the iterable. This, by default, includes any empty (zero-length) iterables. Really, the only way to prevent the else
block from executing is if an explicit break
, return
, exit
or similar is reached within the loop body.
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.
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.
Explore related questions
See similar questions with these tags.
break
is used a lot in "I've found it" loops, you can translate it to "if not found", which is not far from whatelse
readsfor ... else foo()
and just puttingfoo()
after the for loop?" And the answer is that they behave differently only if the loop contains abreak
(as described in detail below).