I have recently stumbled over a seeming inconsistency in Python’s way of dealing with else clauses in different compound statements. Since Python is so well designed, I’m sure that there is a good explanation, but I can’t think of it.
Consider the following:
if condition:
do_something()
else:
do_something_else()
Here, do_something_else() is only executed if condition is false, as expected.
Similarly, in
try:
do_something()
except someException:
pass:
else:
do_something_else()
finally:
cleanup()
do_something_else() is only executed if no exception occurred.
But in for or while loops, an else clause is always executed, whether the contents of the for/while block have been executed or not.
for i in some_iterator:
print(i)
else:
print("Iterator is empty!")
will always print “Iterator is empty!”, whether I say some_iterator = [] or some_iterator = [1,2,3]. Same behavior in while-else clauses. It seems to me that else behaves more like finally in these cases. What am I overlooking?
Well, it depends how you see it. You can look at the elses like this (excuse the screaming, its the only way to make emphasis in code):
Now, there is an obvious similarity between if/else and try/except/else, if you see the else statement as an else to the except statement. Like this.
Same goes for the else/for:
So here we see that the else in some fundamental way do work exactly the same in all three cases.
But you can also see the else in this way:
And then it’s not the same anymore, but the else because a sort of “if nothing else”. You can see for/else in the same way:
But then again, considering the elif, then this way of seeing it works for if/else as well:
Which way you want to look at the else is up to you, but in both ways of viewing, else do have similarities in all three cases.