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

Ron Adam ron3200 at gmail.com
Wed Oct 5 07:30:13 CEST 2011


On Tue, 2011-10-04 at 19:21 -0700, Guido van Rossum wrote:
> 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.

There is also the newer partition and rpartition methods, which I tend
to forget about.


I really don't like the '-1' for a not found case. They just get in the
way.


If len(s) was the not found case, you get a value that can be used in a
slice without first checking the index, or catching an exception.

>>> s[len(s):]
''


Lets say we didn't have a split method and needed to write one.

If s.find returned len(s) as the not found...

def split(s, x):
    result = []
    start = 0
    while start < len(s):
        i = s.find(x, start)
        result.append(s[start:i])   # No check needed here.
        start = i + len(x)
    return result

Of course you could you this same pattern for other things.

cheers,
   Ron


















More information about the Python-ideas mailing list