It’s been said in a couple places (here and here) that Python’s emphasis on “it’s easier to ask for forgiveness than permission” (EAFP) should be tempered with the idea that exceptions should only be called in truly exceptional cases. Consider the following, in which we’re popping and pushing on a priority queue until only one element is left:
import heapq
...
pq = a_list[:]
heapq.heapify(pq)
while True:
min1 = heapq.heappop(pq)
try:
min2 = heapq.heappop(pq)
except IndexError:
break
else
heapq.heappush(pq, min1 + min2)
# do something with min1
The exception is only raised once in len(a_list) iterations of the loop, but it’s not really exceptional, because we know its going to happen eventually. This setup saves us from checking whether a_list is empty a bunch of times, but (maybe) it’s less readable than using explicit conditions.
What’s the consensus on using exceptions for this kind of non-exceptional program logic?
Not in Python: for example, every
forloop (unless it prematurelybreaks orreturns) terminates by an exception (StopIteration) being thrown and caught. So, an exception that happens once per loop is hardly strange to Python — it’s there more often than not!The principle in question may be crucial in other languages, but that’s definitely no reason to apply that principle to Python, where it’s so contrary to the language’s ethos.
In this case I like Jon’s rewrite (which should be further simplified by removing the else branch) because it makes the code more compact — a pragmatical reason, most definitely not the “tempering” of Python style with an alien principle.