[Python-ideas] Deprecate str.find
Terry Reedy
tjreedy at udel.edu
Sat Jul 16 20:46:57 CEST 2011
On 7/15/2011 6:50 PM, Cameron Simpson wrote:
> On 15Jul2011 12:12, Mike Graham<mikegraham at gmail.com> wrote:
>age etc.
>
> str.find does not have a failure mode, it has string found and string
> not found.
Not finding == failure to find == failure to match an implied re.
The question is, how should failure to find be indicated?
Out of band with a exception?
In band with a special value?
(I am here ignoring the design bug that the 'special value' returned by
str.find is not really special in Python but is a legal and common index
and hence bug-bait.)
Python usually chooses one method or the other.
The index/find pair is very exceptional in providing both.
Why? What is so important or exceptional about this particular function?
'Find the index of a substring in a string' is not the most common
operation, at least not for most people.
To me, the special-pleading arguments given for find would apply to a
hundred other functions. For instance, should we add an alternate
constructor for int, say int.nix, that would return None instead of
ValueError for 'string not consisting of 1 or more base x digits'. [
'Nix' here means 'nix, you cannot do that, you get nothing in return'.]
As with index/find, the input string either does or does not match a
particular re. If we have two ways to indicate 'not match' for one
function, why not all others?
<Answer 1> Why not? Because we do not *need* the near duplication
because mis-formed inputs to int are handled with try--except because
that is the way it is done. The duplication of index/find is a
historical aberration with no particular justification other than
history. Leave it at that. If str.find did not exist, a proposal to add
it would be less welcome than int.nix.
<Answer 2> Indeed, choice of failure indicator is good, so lets do it
right and have it everywhere. Define nix generically as
def nix(self, *args, **kwds):
try:
return self(*args, **kwds)
except:
return None
Make this a builtin and add it as a class or instance method, as
appropriate, to appropriate built-in classes. (I am thinking, for
instance, that class method for int and instance method for
type(lambda:0) should work. See test below.) By exposing it, users could
use it too eiher directly or wrapped with classmethod(). Or call the
above _nix and define decorators.
Then str.find would eventually be deprecated in favor of str.index.nix.
A preliminary test:
class C():
def __init__(self, f):
self.f = f
def __call__(self, *args):
return self.f(*args)
def nix(self, *args, **kwds):
try:
return self(*args, **kwds)
except:
return None
myint = C(int)
print(myint('1'), myint.nix('1'), myint.nix(''), myint.nix('a'))
try: myint('')
except: print('E caught')
>>>
1 1 None None
E caught
--
Terry Jan Reedy
More information about the Python-ideas
mailing list