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?
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.
To make it simple, you can think of it like that;
break
command in thefor
loop, theelse
part will not be called.break
command in thefor
loop, theelse
part will be called.In other words, if for loop iteration is not "broken" with
break
, theelse
part will be called.It is so simple.
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:for ... else
construct was devised by Donald Knuth as a replacement for certainGOTO
use cases;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
;"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 theelse
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:* Bonus quote from that part of the video: "Just like if we called lambda makefunction, nobody would ask, 'What does lambda do?'"
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.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: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.