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

MRAB python at mrabarnett.plus.com
Sun Oct 27 20:23:47 CET 2013


On 27/10/2013 18:32, Guido van Rossum wrote:
 > On Sun, Oct 27, 2013 at 10:40 AM, MRAB <python at mrabarnett.plus.com> 
wrote:
 >> On 27/10/2013 17:04, Guido van Rossum wrote:
 >>> In the comments of
 >>> 
http://python-history.blogspot.com/2013/10/why-python-uses-0-based-indexing.html
 >>> there were some complaints about the interpretation of the bounds
 >>> for negative strides, and I have to admin it feels wrong. Where did
 >>> we go wrong? 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:
 >>>
 >>> "abcde"[:1:-1] == "edc"
 >>> "abcde"[:0:-1] == "edcb"
 >>>
 >>> but
 >>>
 >>> "abcde":-1:-1] == ""
 >>>
 >>> I'm guessing it all comes from the semantics I assigned to negative
 >>> stride for range() long ago, unthinkingly combined with the rules
 >>> for negative indices.
 >>
 >> For a positive stride, omitting the second bound is equivalent to
 >> length + 1:
 >>
 >> >>> "abcde"[:6:1]
 >> 'abcde'
 >>
 > Actually, it is equivalent to length; "abcde"[:5:1] == "abcde" too.
 >
 >> For a negative stride, omitting the second bound is equivalent to
 >> -(length + 1):
 >>
 >> >>> "abcde"[:-6:-1]
 >> 'edcba'
 >>
 > Hm, so the idea is that with a negative stride you you should use
 > negative indices. Then at least you get a somewhat useful invariant:
 >
 > if -len(a)-1 <= j <= i <= -1:
 >      len(a[i:j:-1]) == i-j
 >
 > which at least somewhat resembles the invariant for positive indexes
 > and stride:
 >
 > if 0 <= i <= j <= len(a):
 >      len(a[i:j:1]) == j-i
 >
 > For negative indices and stride, we now also get back this nice
 > theorem about adjacent slices:
 >
 > if -len(a)-1 <= i <= -1:
 >      a[:i:-1] + a[i::-1] == a[::-1]
 >
 > Using negative indices also restores the observation that a[i:j:k]
 > produces exactly the items corresponding to the values produced by
 > range(i, j, k).
 >
 > Still, the invariant for negative stride looks less attractive, and
 > the need to use negative indices confuses the matter. Also we end up
 > with -1 corresponding to the position at one end and -len(a)-1
 > corresponding to the position at the other end. The -1 offset feels
 > really wrong here.
 >
The difference might be because the left end is at offset 0 but the
right end is at offset -1.

 > I wonder if it would have been simpler if we had defined a[i:j:-1] as
 > the reverse of a[i:j]?
 >
'range' is defined as range(start, stop, stride).

Some examples from other languages:

BASIC:

     for i = start to stop step stride

Pascal:

     for i := start to stop do
     for i := start downto stop do

The order of start and stop is the same.

If you're slicing in reverse order, then the current order of the start
and stop positions seeks reasonable to me.

 > What are real use cases for negative strides?
 >


More information about the Python-ideas mailing list