dbf.py API question concerning Index.index_search()
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Wed Aug 15 20:52:10 EDT 2012
On Wed, 15 Aug 2012 16:26:09 -0700, Ethan Furman wrote:
> Indexes have a new method (rebirth of an old one, really):
>
> .index_search(
> match,
> start=None,
> stop=None,
> nearest=False,
> partial=False )
[...]
Why "index_search" rather than just "search"?
> The question is what should the return value be?
>
> I don't like the usual pattern of -1 meaning not found (as in
> 'nothere'.find('a'))
And you are right not to. The problem with returning -1 as a "not found"
sentinel is that if it is mistakenly used where you would use a "found"
result, your code silently does the wrong thing instead of giving an
exception.
So pick a sentinel value which *cannot* be used as a successful found
result.
Since successful searches return integer offsets (yes?), one possible
sentinel might be None. (That's what re.search and re.match return
instead of a MatchObject.) But first ensure that None is *not* valid
input to any of your methods that take an integer.
For example, if str.find was changed to return None instead of -1 that
would not solve the problem, because None is a valid argument for slices:
p = mystring.find(":")
print(mystring[p:-1]) # Oops, no better with None
You don't have to predict every imaginable failure mode or defend against
utterly incompetent programmers, just against the obvious failure modes.
If None is not suitable as a sentinel, create a constant value that can't
be mistaken for anything else:
class NotFoundType(object):
def __repr__(self):
return "Not Found"
__str__ = __repr__
NOTFOUND = NotFoundType()
del NotFoundType
and then return that.
(By the way, I'm assuming that negative offsets are valid for your
application. If they aren't, then using -1 as sentinel is perfectly safe,
since passing a "not found" -1 as offset to another method will result in
an immediate exception.)
> The other option is returning a (number, bool) tuple -- safer, yet more
> boring... ;)
Boring is good, but it is also a PITA to use, and that's not good. I
never remember whether the signature is (offset, flag) or (flag, offset),
and if you get it wrong, your code will probably fail silently:
py> flag, offset = (23, False) # Oops, I got it wrong.
py> if flag:
... print("hello world"[offset+1:])
...
ello world
--
Steven
More information about the Python-list
mailing list