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

Guido van Rossum guido at python.org
Wed Oct 5 04:21:21 CEST 2011


On Tue, Oct 4, 2011 at 4:13 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> Carl Matthew Johnson wrote:
>
>> This reminds me of the string.index vs. string.find discussion we had
>> a while back. In basically any situation where an exception can be
>> raised, it's sometimes nice to return a None-like value and sometimes
>> nice to have an out-of-band exception. I have a certain amount of
>> admiration for the pattern in Go of returning (value, error) from
>> most functions that might have an error, but for Python as it is
>> today, there's no One Obvious Way to Do It yet, and there's probably
>> none forthcoming.
>
> I beg to differ. Raising an exception *is* the One Obvious Way in Python.
> But OOW does not mean "Only One Way", and the existence of raise doesn't
> mean that there can't be a Second Not-So-Obvious Way, such as returning a
> "not found" value.
>
> However, returning None as re.match does is better than returning -1 as
> str.find does, as -1 can be mistaken for a valid result but None can't be.

What works for re.match doesn't work for str.find. With re.match, the
result when cast to bool is true when there's a match and false when
there isn't. That's elegant.

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. Hence the -1: the intent
was that people should write "if s.find(x) >= 0" -- but clearly that
didn't work out either, it's too easy to forget the ">= 0" part. We
also have str.index which raised an exception, but people dislike
writing try/except blocks. We now have "if x in s" for situations
where you don't care where the match occurred, but unfortunately if
you need to check whether *and* where a match occurred, your options
are str.find (easy to forget the ">= 0" part), str.index (cumbersome
to write the try/except block), or "if x in s: i = s.index(x); ..."
which looks compact but does a redundant second linear search. (It is
also too attractive since it can be used without introducing a
variable.)

Other ideas: returning some more structured object than an integer
(like re.match does) feels like overkill, and returning an (index,
success) tuple is begging for lots of mysterious occurrences of [0] or
[1].

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.

-- 
--Guido van Rossum (python.org/~guido)



More information about the Python-ideas mailing list