[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