[Python-ideas] Where did we go wrong with negative stride?

Tim Peters tim.peters at gmail.com
Sun Oct 27 19:38:05 CET 2013


I may have a different slant on this.  I've found that - by far - the
most successful way to "teach slices" to newcomers is to invite them
to view indices as being _between_ sequence elements.

<position 0> <element> <position 1> <element> <position 2> <element>
<position 3> ...

Then i:j selects the elements between position i and position j.

>>> "abcde"[2:4]
'cd'

But for negative strides this is all screwed up ;-)

>>> "abcde"[4:2:-1]
'ed'

They're not getting the elements between "positions" 2 and 4 then,
they're getting the elements between positions 3 and 5.  Why?
"Because that's how it works" - they have to switch from thinking
about positions to thinking about array indexing.

So I would prefer that the i:j in s[i:j:k] _always_ specify the
positions in play:

If i < 0:
    i += len(s)  # same as now
if j < 0:
    j += len(s)  # same as now
if i >= j:
    the slice is empty!  # this is different - the sign of k is irrelevant
else:
    the slice indices selected will be
        i, i + abs(k), i + 2*abs(k), ...
    up to but not including j
    if k is negative, this index sequence will be taken in reverse order

Then "abcde"[4:2:-1} would be "", while "abcde"[2:4:-1] would be "dc",
the reverse of "abcde"[2:4].  And s[0:len(s):-1] would be the same as
reversed(s).

So it's always a semi-open range, inclusive "at the left" and
exclusive "at the right".  But that's more a detail:  the _point_ is
to preserve the mental model of selecting the elements "between
position".  Of course I'd change range() similarly.


[Guido]
> For example,
>
> "abcde"[::-1] == "edcba"
>
> as you'd expect, but there is no number you can put as the second bound to
> get the same result:

Actually, any integer <= -1-len("abcde") = --6 works.  But, yes,
that's bizarre ;-)

>...
> Are we stuck with this forever?

Probably :-(

> ...


More information about the Python-ideas mailing list