[Python-ideas] str.rreplace

Steven D'Aprano steve at pearwood.info
Tue Jan 28 13:33:50 CET 2014


On Mon, Jan 27, 2014 at 08:03:54PM -0800, Andrew Barnert wrote:
> From: Ron Adam <ron3200 at gmail.com>

> > How about a keyword to specify which end to index from?

-1

As a general rule, when you have a function that takes a parameter which 
selects between two different sets of behaviour, and you normally 
specify that parameter as a literal or constant known at edit time, then 
the function should be split into two.

E.g.:

# Good API
string.upper(), string.lower()

# Bad API
string.convert_case(to_upper=True|False)

sorted() and list.sort() (for example) are a counter-example. Sometimes 
you know which direction you want at edit-time, but there are many 
use-cases for leaving the decision to run-time. Nearly every application 
that sorts data lets the user decide which direction to sort.

In the case of replace/rreplace, it is more like the upper vs. lower 
situation than the sorted situation. For almost any reasonable use-case, 
you will know at edit-time whether you want to go from the left or from 
the right, so you'll specify the "direction" parameter as a edit-time 
literal or constant. The same applies to find/rfind.


> >  When used, it would 
> > disable negative indexing as well.

-1

Negative indexing is a standard Python feature. There is nothing wrong 
with negative indexing, no more than there is something wrong with 
zero-based positive indexing.

It's also irrelevant to the replace/rreplace example, since replace 
doesn't take start/end indexes, and presumably rreplace wouldn't either.


> > When not used the current behaviour with 
> > negative indexing would be the default.
>> 
> >     direction=0            # The default with the current
> >     (or not specified)     #    negative indexing allowed.
> > 
> >     direction=1   # From first. Negative indexing disallowed.
> >     direction=-1  # From last.  Negative indexing disallowed.

And if you want to operate from the right, with negative indexing 
allowed? But really, having a flag to decide whether to allow negative 
indexing is silly. If you don't want negative indexes, just don't use 
them. 


> > (A shorter key word would be nice, but I can't think of any that is as 
> > clear.)
> 
> Why does it have to be -1/0/1 instead of just True/False?
> 
> In which case we could use "reverse", the same name that's already 
> used for similar things in other methods like list.sort (and that's 
> implied in the current names "rfind", etc.).

sorted(alist, reverse=True) gives the same result as sorted(alist, 
reverse=False) only reversed. That is not the case here:

    "Hello world".replace("o", "u", 1, reverse=True)  # rreplace

ought to return "Hello wurld", not "dlrow ulleH".


> > The reason for turning off the negative indexing is it would also offer a way to 
> 
> > avoid some indexing bugs as well.  (Using negative indexing with a reversed 
> > index is just asking for trouble I think.)
> 
> But str.rfind takes negative indices today:
> 
>     >>> 'abccba'.rfind('b', -5, -3)
>     1
> 
> Why take away functionality that already works?

Exactly. Here, I agree strongly with Andrew. Negative indexing works 
perfectly well with find/rfind. Slices with negative strides are weird, 
but negative indexes are well-defined and easy to understand.


> And of course str.find takes negative indices and that's actually used 
> in some quick&dirty scripts:
> 
>     >>> has_ext = path.find('.', -4)
> 
> Of course you could make an argument that any such scripts deserve to 
> be broken…

It would be an awfully bogus argument. Negative indexes are a 
well-defined part of Python indexing semantics. One might as well argue 
that any scripts that rely on list slicing making a copy "deserve to be 
broken".


-- 
Steven


More information about the Python-ideas mailing list