[Python-ideas] Default return values to int and float

Steven D'Aprano steve at pearwood.info
Sat Oct 8 03:45:44 CEST 2011


Terry Reedy wrote:
> On 10/4/2011 10:21 PM, Guido van Rossum wrote:
> 
>> But with str.find, 0 is a legitimate result, so if we were to return
>> None there'd be *two* outcomes mapping to false: no match, or a match
>> at the start of the string, which is no good.
> 
> People would have to test that the result 'is None' or 'is not None'. 
> That is no worse than testing '== -1' or '>= 0'. I claim it is better 
> because continuing to compute with None as if it were a number will more 
> likely quickly raise an error, whereas doing so with a '-1' that looks 
> like a legitimate string position (the last), but does not really mean 
> that, might never raise an error but lead to erroneous output. (I said 
> 'more likely' because None is valid in slicings, same as -1.)

Agreed.

But...

[...]
>> I'm out of ideas here. But of all these, str.find is probably still
>> the worst -- I've flagged bugs caused by it too many times to count.
> 
> So lets deprecate it for eventual removal, maybe in Py4.

Let's not.

Although I stand by my earlier claim that "raise an exception" is the
Obvious Way to deal with error conditions in Python, for some reason
that logic doesn't seem to apply to searching. Perhaps because "not 
found" is not an error, it just feels uncomfortable, to many people. 
Whenever I use list.index, I always find myself missing list.find.

Perhaps it is because using try...except requires more effort. It just
feels wrong to write (for example):

try:
     n = s.index('spam')
except ValueError:
     pass
else:
     s = s[n:]

instead of:

n = s.find('spam')
if n >= 0:
     s = s[n:]


This is especially a factor when using the interactive interpreter.

(I also wonder about the performance hit of catching an exception vs.
testing the return code. In a tight loop, catching the exceptions may be
costly.)

I don't think there is any perfect solution here, but allowing people
the choice between index and find seems like a good plan to me. Using -1
as the not-found sentinel seems to be a mistake though, None would have
been better. That None is valid in slices is actually a point in it's
favour for at least two use-cases:


# extract everything after the substring (inclusive)
# or the entire string if not found
n = s.find('spam')
substr = s[n:]

# extract everything before the substring (exclusive)
# or the entire string if not found
n = s.find('spam')
substr = s[:n]


There are other cases, of course, but using None instead of -1 will 
generally give you an exception pretty quickly instead of silently doing 
the wrong thing.



-- 
Steven




More information about the Python-ideas mailing list