9 ms·
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 happe
by askvictor 8y ago
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:
for i in l:
print(i)
then:
print("iteration finished without breaking")
- jacobolus 8y agoThey probably used the word "else" to cut down on the number of reserved keywords, and for consistency with try / except / else.
- deleted 8y ago[deleted]
- kazinator 8y agoIt is consistent with the idea that it provides an alternative clause to a failing loop guard. Using the much clearer C syntax as pseudo-code, suppose we have this: for (;;) { if (loop_guard()) { body; } else { alternative; break; } } We can imagine an extension to while which lets us rewrite it like this: while (loop_guard()) { body; } else { alternative; } Based on this framing, there is justification in calling it else. The runs counter to an intuition which would like it to be this: if (loop_guard()) { while (loop_guard()) { body; } } else { alternative; } I.e. not an alternative in the face of the failed loop guard on every iteration, but just the first loop guard test: an alternative to the loop when no iterations take place.
- rlayton2 8y agoI'm a strong python advocate and rarely use for/else for this exact reason. It makes more sense to me for it to be the other way (your way) around. I always add a comment on the else when I do too, to ensure that future readers don't make the same mistake.
- deleted 8y ago[deleted]
- bjd2385 8y agoI agree. It's seldom something I've used in my scripts/small projects for this exact reason. It should also be noted that there is a `while-else` compound statement as well, wherein using a `break` immediately exits the loop, without executing the `else` clause [1]. [1] https://docs.python.org/3/reference/compound_stmts.html#the-while-statement https://docs.python.org/3/reference/compound_stmts.html#the-...
- kchr 8y agoYeah, it really feels (almost in a physical sense) like an anti-pattern... I have to force my fingers to write it.
- joelcornett 8y agoI’ve never found a compelling reason to use this construct (or the analogous `while...else` construct). But then again, I rarely find myself using `else` with `if` either...
- shawnz 8y agoIt makes sense to me in the specific context of using it to respond to an item not being found in a list. In other contexts, I agree that the word is not a good fit.
- georgyo 8y agoThe else makes perfect sense. The for loop keeps going as long as the condition is true. When the condition is false, it exits the loop without breaking. Else acts on the condition being false.
- Nition 8y agoBut the else fires in Python if the loop does not break. It sounds like you're saying the opposite. Even if you aren't, I think we can agree it's potentially confusing.
- georgyo 8y agoThis is the correct place for it to do so. Break skips the check entirely. If the for loop exits normally, the condition was false.
- Nition 8y agoYou understand that it can be a confusing code construct though, right? Even in your comments I'm kind of confused at your meaning because you said: > When the condition is false, it breaks. And then you said: > If the for loop exits normally, the condition was false.
- georgyo 8y agoI have updated that comment, a normal loop exit is not the same as a break. I can understand how it can be confusing, but the inverse would not make any sense. Another way to look at a for loop is a fancy while loop that sets a variable by some function. Every loop iteration that function is ran. If the function fails, the loop exits. This is infact how they work. https://anandology.com/python-practice-book/iterators.html#the-iteration-protocol https://anandology.com/python-practice-book/iterators.html#t... If next() fails, that is when the loop exits.
- deleted 8y ago[deleted]
- mlthoughts2018 8y agoI don’t like this feature of Python, but I have come to disagree with what you mention, even though I understand your point. For example, from [0], it’s described as: > “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.” So it is very analogous to an if / else statement: the “else” after a for or while loop directly means the conditional of the loop evaluated to False. If the program never reaches a state in which the loop conditional evaluates to False, then the else block is not entered. Just like: only when the conditional of an if statement evaluates to False will the else block be entered. After I understood this, I started to think that break is really the more problematic thing, because it means more like a goto sort of jump, abandoning the status of the variables governing the loop condition. But again, I don’t like these loop-else features. They definitely violate least surprise for most people reading the code. [0]: < https://stackoverflow.com/questions/3295938/else-clause-on-python-while-statement#3295949 https://stackoverflow.com/questions/3295938/else-clause-on-p... >
- thaumasiotes 8y ago> So it is very analogous to an if / else statement: the “else” after a for or while loop directly means the conditional of the loop evaluated to False. ...how is that supposed to apply to "for i in l"? What is the conditional? I don't think of python for statements as involving conditionals at all; you seem to be describing a while/else rather than a for/else.
- kqr 8y agoThink along the lines of "for (l = lst.iterate(); l != null; l.next())".
- mlthoughts2018 8y agoThis is right; it’s the StopIteration exception (which is fundamental to what a for loop does in Python). Not saying is absolves the for/while else syntax, but it’s still using the expected iteration constructs.
- yk 8y agoWhen I thought about this, I first agreed, then I thought that from the perspective of the interpreter it is else as in checks the condition and then goes to else if the condition is false. So I think it is not so much unintuitive, as it is consistent in a not immediately intuitive way.
- sound1 8y agoAgree completely. I think for-else is same as if-else in that if the condition satisfies then it executes the main loop and if not it executes the 'else'.
- logicallee 8y agoI like it! Makes perfect sense, it's short, and since then "belongs to" the for, it makes sense for a break or exception to break out of both. On the other hand, under your suggestion someone still has to learn the meaning of then, it's not fully explicit. Since "Explicit is better than Implicit", if we are not optimizing for brevity I have these two suggestions that are more explicit alternatives to your then suggestion. -------- Suggestion 1 (horrific suggestion): Call this keyword finally. This implies that no matter what the finally part will execute. This is like defining never as a synonym for true, so that if(never) always executes. Why would anyone ever do that!! Hardly any choice in a design is as bad as explicitly saying something different from what will happen. So this is a terrible suggestion. -------- Suggestion 2 (good suggestion): Call this keyword ifthru. (Thru being an abbreviation for through). As it says, this one will run if the loop completed. Another way to read it is if execution continued "through" the end. So your example might read: for i in l: print(i) ifthru: print("iteration finished without breaking or exceptions") This is extremely explicit about the condition. I picked it to be short while remaining explicit. The elif keyword is an existing precedent for mispelling for the sake of brevity. It also alerts the reader that logically there is a condition here. After all, semantically every block could start with the "then" word in English. Semantically, when you break you could also be considered to be "through" however in this case the ifthru keyword wouldn't serve any purpose at all, since it could just be on the next line. The "if" alerts the reader that there's a condition here.. I hope you'll agree that my second suggestion is pretty good :)
- p1necone 8y agoFwiw my initial assumption (as a non python dev) was that the else statement would execute once the loop condition was false (including the case where loop condition was never true).
- zephyrfalcon 8y agoI agree that the word 'else' is confusing here. To me, it suggests that one thing is done, or the other, but not both. Python's try..except..else follows this pattern, but for..else and while..else do not, for some reason.
- ehsankia 8y agoEvery time I go to use for...else, I need to look up what the behavior is, I can never remember if it's hitting the break or not hitting the break. That being said, python always tries to minimize the number of keywords, so re-using else makes more sense then introducing a whole new keyword for a niche usecase.
- fjsolwmv 8y ago...and then you realize that's why you shouldn't use it, right?
- fyi1183 8y agoThe way I remember it is that it makes sense in loops that search for something in an iterable. Such loops break when they're successful, and so it makes sense for the code in the else clause to run when the loop was unsuccessful.
- seandougall 8y agoAgreed. I can see where the design is coming from, but this coupled with the reliance on indentation to delineate scope means that it’s really visually confusing — I expect the `else` to correspond to the `if` statement when I see it in the context of the given example. It’s not strictly ambiguous, but it’s certainly an impediment to readability.
- vqng 8y agoI am not a native speaker but I think "done" or "finished" is better. "else" is a counterpart of "break". It assumes people must think of "break" whenever they see a "for", which is not always the case. We refer to this weirdness as Pythonic.
- combatentropy 8y agoThe Handlebars template engine works the way you're talking about. The "each" helper loops through an array. You can put in an "else" block for when the array is empty. {{#each paragraphs}} <p>{{this}}</p> {{else}} <p class="empty">No content</p> {{/each}} --- https://handlebarsjs.com/builtin_helpers.html https://handlebarsjs.com/builtin_helpers.html
- tzs 8y ago> 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 Suppose it worked like that and you had this code: for i in l: A() if B(): break C() else: D() Wouldn't that be equivalent to: for i in l: A() if B(): D() break C() What your suggested else is doing is providing a place to put code to execute after a break in the loop, but we already have a place for such code: immediately in front of the break in the loop. The only place that comes to mind where this would be useful is situations where you there is more than one if ...: D() break in the loop. With your suggested kind of else, you could move all the D()'s to an else after the loop.
- deleted 8y ago[deleted]
- Animats 8y agoYes, "then" would have been a better choice. But "then" isn't a keyword in Python. "else" is used with try blocks to indicate the exception didn't take place. It makes more sense there, because it follows the "except" sections.
- jimmytucson 8y agoHere’s why (Hettinger): > In 1991, “else” was the obvious choice because of the traditional way compilers implemented while-loops: pastebin.com/tY35CTJ4 That is, “if I haven’t finished the loop, GOTO the body.” He says if he had a time machine he could tell Guido in the future we’re all using structured programming so no one will find “else” intuitive; call it “nobreak” instead: https://m.youtube.com/watch?v=OSGv2VnC0go# https://m.youtube.com/watch?v=OSGv2VnC0go# Guido says if he had a time machine he would not have included the feature at all: https://mail.python.org/pipermail/python-ideas/2009-October/006157.html https://mail.python.org/pipermail/python-ideas/2009-October/... This whole thing was Knuth’s idea, not Guido’s: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.103.6084&rep=rep1&type=pdf http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.103...
- pmontra 8y ago> Guido says if he had a time machine he would not have included the feature at all So deprecate it with a runtime warning and remove it after some years. I wonder if there are some statistics about its usage. I guess it's very low.
- noobermin 8y agoWhy remove a feature that could be useful? That makes no sense. Just because it isn't named in a way people find intuitive doesn't mean it isn't useful.
- some_account 8y agoGoto is also useful... See why now?
- reificator 8y agoThis comment contains more snark than content, but I'll reply anyway: Goto is considered harmful, but it's important to recognize the context of that decision rather than parroting the idea. It's not an obvious idea and if the discussion had happened today with modern languages[0] instead it's not at all obvious the same conclusions would be reached. This write-up does a pretty fair job of translating the original paper to something more modern without a lot of bias. http://david.tribble.com/text/goto.html http://david.tribble.com/text/goto.html [0]: Modern languages of course learned from this paper, so that's not a fair comparison. In fact golang contains a goto, but it behaves well according to Dijkstra's concerns and occasionally results in more readable code. I would be shocked if Dijkstra took any issue with go's implementation.
- pasta1212 8y ago"Then" implies that the associated code will always run after the for loop completes, which isn't true either. Maybe "complete" is a decent choice. I'm sure language keywords are an issue here, too.
- Doxin 8y agoIt always made sense to me since I think about these constructs as the loop searching for something (and breaking if it finds it) and the else running if nothing was found. for item in list: if search_condition: found_item=item break else: found_item=default_item
- hughdbrown 8y agoAs an alternative, you could do this: found_item = next((item for item in list if search_condition), default_item)
- gbin 8y agoHonestly it is not a big deal, just remember the else is for the break, not the for. Then it reads naturally: for this break else do that.
- farzher 8y agoit should be called nobreak that explains exactly what it does