The word else implies something different to what it does (IMHO at least). In and if/else clause, the else happens when the primary/expected thing doesn't happen. I would expect that for a loop, an else clause would happen when the loop does _not_ finish normally, or if they loop is empty. I'm sure it's a useful clause in certain cases, but the meaning of the word used is reversed. It might be better use 'then' or something like that:<p><pre><code> for i in l:
print(i)
then:
print("iteration finished without breaking")</code></pre>
I love Python's for-else feature. I've used it on a number of occasions, and have found it to be useful and to cut down on code.<p>However, I agree that the use of "else" is horribly confusing. When I teach "for-else" to students in my Python courses, they are often surprised by the functionality, and doubly surprised that the word "else" is used. I often joke that it would be a great feature, if only they had chosen something a bit more intuitive and memorable instead of "else", such as "if_we_exited_the_block_without_encountering_a_break". Slightly more seriously: While I realize that adding a keyword to Python isn't in the cards, a word such as "nobreak" would be easier for people to understand, and would stress the point of the functionality.<p>The fact that Emacs always tries to indent the "else" of a "for-else" to align with an "if" inside of the loop, rather than the "for" with which it matches, speaks volumes. I mean, if Emacs is confused, then how are we mere mortals supposed to remember?<p>So when I use "for-else", it's almost always in code that I am writing for myself, and that I don't expect others to read or maintain.<p>Don't forget that there's also "while-else", although I can't remember the last time I saw that actually used.
Yes the for...else is useful but for years it didn't do what I expected, which is execute when the sequence was empty. After reading the docs a half dozen times I finally internalized that the else actually means "not broken," aka "not found."<p>So now when I use it, I always put a comment next to it for myself and the next person:<p><pre><code> for item in items:
if found:
break
else: # no-break
print('not found.')</code></pre>
<a href="https://twitpic.com/4a52sh" rel="nofollow">https://twitpic.com/4a52sh</a><p>A survey on this feature was done at Pycon 2011. Maybe things have changed since then, but at the time, most people didn't understand what for/else did.<p>I think it's a bad construct because, as many have mentioned, a lot of people make the commonsense interpretation that the else block will only execute if the for block did not.<p>Note, the link above come via Jeremy Avnet in the comments of this blog post.<p><a href="https://nedbatchelder.com/blog/201110/forelse.html" rel="nofollow">https://nedbatchelder.com/blog/201110/forelse.html</a>
I've used the loop -> else construct sparingly - there are times when it is really convenient.<p>But it is VERY confusing.<p>Its very confusing, and poor design - IMHO - because the presence of an "else" block, in the typical case, generally indicates that the preceding block was never executed.<p>When it comes to while/for blocks in python, the keyword literally indicates the opposite - that the preceding block executed without hiccups - and so also execute this block.<p>Its a great feature - but there should have been another keyword for it: "also" (or something like that)
The fact that so many commenters here are confused or surprised by what it means or how it works sort of proves to me that it is a bad idea to use this in your code-- especially if anyone else might need to work on that code. I always prefer the clearer, obvious approach, even it is slightly longer.
Oh, that didn't do what I expected at all.<p>I was expecting this to be similar to:<p><pre><code> if list: for x in list:
# Some code
else:
# else clause
</code></pre>
which would have been quite useful to have for general iterators. But apparently it's a statement that triggers <i>unless</i> you use 'break' to end the loop, which just seems like a really weird use case, and smells like a goto.
I hate adding syntax but you know what's really useful? Django's `for .. empty` template syntax.<p>I would like to see this in Python:<p><pre><code> for i in []:
print(i)
empty:
print("Sequence was empty!")</code></pre>
I've been using this for years and never thought twice about it, I'm shocked by all the negativity.<p>It's great for controlling iteration in a nested loop:<p><pre><code> for item in report():
for event in in item['events']:
if event in events_we_care_about:
break
else:
continue
act_upon(item)
</code></pre>
I realize it's a trivial example that could be written without a nested loop, but there are often good reasons for nested loops and littering them with control variables and if statements gets messy quick. I have always found for-else to produce more elegant code.<p>Your criticisms may be quite valid, I just wanted to share my surprise.
To me, the else isn’t intuitive if you haven’t encountered it before. It’s a nice feature, but perhaps better naming could improve code readability.<p>How about for-finally? It’s a hard thing to name correctly, but to me this seems to be slightly more intuitive if you’ve never seen the feature before.
I had my first legitimate use of for else last week after knowing about it for years and it (the keyword) never making much sense.<p>I had to call an API for it to load data into a cache, but sometimes this wouldn't work so I made it try up to 3 times, otherwise it would show an error. So something like:<p><pre><code> for i in range(3):
if load_cache():
log("success")
break
else:
log("failure")
</code></pre>
Else made total sense here.
Nearly everybody seems surprised by what it does, which would appear to constitute a fairly strong violation of the "principle of least surprise" that is one of the most cited guiding principles employed by the designers of Python. As such it would seem better to be described as an "anti-tip" or something like that.
It is worth noting that the else clause can also be used with while loops.<p>[1]: <a href="https://docs.python.org/3.6/reference/compound_stmts.html#while" rel="nofollow">https://docs.python.org/3.6/reference/compound_stmts.html#wh...</a>
While this is a great capability to have, the tendency to have an indented “if” preceding a not-indented “else” just always seems like somebody might have made a mistake.<p>I would rather something that captures the loop state itself as an operable object, such as:<p><pre><code> with for as loop:
for x in my_list:
...
if not loop.broken:
...</code></pre>
One thing that for-else is very useful for is implementing an elegant and easy-to-understand retry mechanism:<p><pre><code> for _ in range(3):
success = do_something()
if success:
break
else:
raise FailedToDoSomething
</code></pre>
I generally like this feature of the for loop and it would be a shame if it was removed.
I find this pattern very much better expressed with functional programming:<p><pre><code> item = next((item for item in container if search_something(item)), None)
if item:
process(item)
else:
not_found_in_container()
</code></pre>
instead of as suggested in the blog post:<p><pre><code> for item in container:
if search_something(item):
# Found it!
process(item)
break
else:
# Didn't find anything..
not_found_in_container()</code></pre>
Since Python doesn't have goto statements, this removes one of the situations where a goto statement is the best tool to use in a language like C++.
This is strongly advised against in the book Effective Python as the semantics are opposite to what one is used to. The else clause will always be executed unless there's a 'break' in the for-loop.
Well, that’s a dumb feature. Very counterintuitive, requires you to stop and think, and there’s a high probability that it’ll be misunderstood at first glance. I hate things like this - you’ll read it, think you understand it, experience a bug, spend hours debugging, then finally look up the documentation for ‘else’ and see that it means something different from what you thought.
I write quite often something like that:<p><pre><code> for i in range(10):
for j in range(10):
if condition(i,j):
dosomething
break
else:
continue
break
</code></pre>
It's a pattern that ensure that dosometing
is run at most once by "propagating" the
break to the outer loop.<p>The alternative is use a function and do a return.<p>Any though of this ?
I'm in favour of writing simple python that even a junior dev can read rather than using niche syntax tricks. Guess that depends on whether you think a junior should know this syntax.
I can't see this ever being used. As a non-python programmer, if I ran across this it would be very confusing. If it's simple enough to write the same code without the else block and have your code be more readable, why not do that?
I much more frequently wish that I could express 'or do this if zero iterations' than I use for-else as it is; I do so wish it had the former semantic.<p>That and the absence of do-while are the cause of a good deal of non-DRY python around loops.
The `else` clause follows the same general pattern wherever it supported: `for`, `while` and `try` are consistent. It usually makes code shorter or at least leads to narrowing concerns when used with `try`.<p>For some reason I often forget to use it though.
I would never include this in my code. It’s a construct most devs have never seen in Python and it differs from anything I’ve seen in other languages.<p>Always KISS.
I hate it when code uses weird niche features that are not obvious, are impossible to look up and add 0 value aside from saving a couple of lines of code.
This is coincidentally my highest rated Stackoverflow answer ever. :)<p><a href="https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops" rel="nofollow">https://stackoverflow.com/questions/9979970/why-does-python-...</a><p>Tl;dr my highly opinionated opinion is that one should never use the construct
For-else is nothing. The really weird one is the Try-else.<p>The For/While-else does exactly what I expect. I'm not sure why others find it confusing.<p>The Try-else does make some code more readable but is quite rare I would say.
This is discussed as item 12 in Effective Python. The author argues that you should avoid "else" blocks after "for" and "while" loops. The main argument is that the behavior is not intuitive and could be confusing upon reading given its somewhat obscure usage.<p>He suggests using a helper function with an early exit or setting a result variable and using a break in your loop instead.