LBYL vs EAFP
Terry Reedy
tjreedy at udel.edu
Tue Feb 5 02:53:50 EST 2013
On 2/4/2013 6:16 PM, Steven D'Aprano wrote:
> The eternal conflict between "Look Before You Leap" and "Easier to Ask for
> Forgiveness than Permission" (LBYL vs EAFP) continues...
A somewhat different answer is that it depends on what you want the
function to do, as documented and *tested*. And that partly depends on
whether it is educational code for humans, production app code, or
library code.
The test driven approach would be to write tests and then do what is
needed to get them to pass. Doctests, unittests, and my private function
test functions allow testing for raising a particular exception.
AssertRaises() is used, perhaps increasingly, in stdlib tests. The
absence of any tests for the response to 'bad' input suggests that the
responses are 'undefined'.
That said, I admit that Python's extensible class system makes bad-input
testing harder. I also think that anyone who uses non-builtin classes
outside of their intended use area has to take responsibility.
For instance:
def f(n, a):
if n < 0: raise ValueError('n cannot be negative')
b = 0
while n:
b = process(a, b)
n -= 1
looks like a safe LBYL function. But suppose n is an instance of a class
that perversely implements subtraction as addition (or as doing
nothing). Algorithm termination is based on the presumption that
'decrementing' a 'positive value' moves it 'toward 0' and can only be
done a finite number of times. Verifying that an input is a member of
that abstract class is not trivial ;-).
> A third option is not to check x at all, and hope that it will blow
> up at some arbitrary place in the middle of my code rather than
> silently do the wrong thing.
A silent infinite loop is bad. Infinite recursion stopped with the
recursion limit check is less bad.
If tests pass with no check, then nothing need be done until one moves
from correctness to resource use.
--
Terry Jan Reedy
More information about the Python-list
mailing list