Terry Reedy tjreedy at
Tue Feb 5 08:53:50 CET 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