4 ms·
I 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 descri
by mlthoughts2018 8y ago
I 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.
- thaumasiotes 8y agoWouldn't that imply that the equivalent of a while/else loop would be a for/except loop, not a for/else loop?
- mlthoughts2018 8y agoAs a matter of trivia, probably not. The iteration mechanism just happens to check for StopIteration, and does not automatically handle any other type of Exception, which would require a usual try block. So StopIteration can be thought of as an equivalent idea to “emptiness” of an iterator, either an empty container, an exhausted generator, etc. And since emptiness is most often handled as falsiness in a bool context, it’s in some sense the natural notion of a “false” iteration condition. This is all incredible mental gymnastics though. But (speaking as someone who loves Python) there’s unfortunately a lot of that in Python.
- fjsolwmv 8y agoThat's deeply "unpythonic"
- tzs 8y ago> ...how is that supposed to apply to "for i in l"? What is the conditional? Presumably there is a conditional in the loop body that decides whether or not to break: for i in l: if ...: break Think of the else clause as being what to do if nothing takes the if in the body. Same for while...else. You'd only be using an else on a while if there was something in the while that could break, so it is whether or not the conditional that controls that decision happens or not that determines whether the else path is taken.
- thaumasiotes 8y agoHuh? Judging by every other comment in the thread, the point of for/else is that breaking does not trigger the else clause. The else clause is triggered when the loop condition is tested and fails... but Python's for doesn't have a loop condition.
- gh02t 8y agoNo, an explicit break skips the else clause and the else clause is evaluated if and only if the iterator in the loop raises a StopIteration exception (i.e., it's exhausted). For example, this code will still evaluate the else clause even though the break statement is always true, because iter([]).next() throws StopIteration immediately: for i in []: if True: break else: print("Foo") while this will not: for i in [1] if True: break else: print("Bar") The "conditional" in a for loop is that the iterator (l in your example) raises a StopIteration exception. I don't really like calling it a conditional though, because it's actually handled as an exception. I guess you could think of the condition being "are there any items remaining in l? If 'no' then evaluate the else clause." I've always considered the else clause on a for loop's proper purpose being to catch erroneous cases, for instance if you try and loop over files in an empty directory. Or if you have no matches searching line by line over a file. Etc.
- noobermin 8y agoYou're right, technically, but the way tzs thinks about it can still be correct if one thinks about it this way: the if statement in your first loop is mathematically true, but it is never executed because [] is of course empty. It's not about whether the inner if ...: break statement's conditional can evaluate to true. A lazy way to think about it is that way, but as long as you remember that it's what occurs when there is no break it's fine.
- reificator 8y agoIf python used C style loops rather than pushing iterators/generators so hard, I would buy that reasoning. But where's the conditional statement in `for i in range(0,10)`? Now, clearly there is a check to see if it's still producing values. But it's intentionally hidden from a surface-level reading of the code. Naming a control structure `else` when it intentionally does not have a clear conditional tied to it is odd to say the least. But it's worse than that- the else clause is supposed to be the normal flow of the program. Programming introductions (fresh in the minds of many who use Python as it's targeted as user-friendly) often stress the fact that in an if/else statement only one or the other block is executed. But this flips that idea upside-down.
- mlthoughts2018 8y agoIt would be the implicit StopIteration exception from the resulting iterator, but I completely agree this can easily be seen as inconsistent / surprising, which is among the reasons why I don’t like it.
- reificator 8y agoThanks for the clarification, I don't use python very often myself. That does underscore that there's really not a normal conditional there though.
- SamReidHughes 8y agoI don't think it violates any important least-surprise principle. You might be surprised to see it used -- but you don't get surprised when the code behaves how the documentation says it will.
- fjsolwmv 8y agoLeast surprise doesn't mean everything is documented. It means things behave analogously to everything else
- ergothus 8y agoBut language attempts to resemble spoken language precisely so we don't have to rely on the documentation alone. We use if/else, not "xan/ka" because we want to leverage the existing meaning of those words. In the early stages of Perl 6 design I requested a for/else feature where the "else" block fired if and only if the for loop had never been entered...the opposite of how this works. Being literally the opposite of how I would write it qualifies as surprising to me.
- SamReidHughes 8y agoNaming is useful for getting adoption but not when you already know the language. And in your case you might have been surprised, but that's because you'd take a guess at what the feature does instead of finding out. (I don't think for/else is the best option, gotos are. It's just not a harmful feature, the way other aspects of Python are.)