negative stride list slices

Peter Otten __peter__ at web.de
Wed Sep 1 20:51:04 CEST 2004


David Abrahams wrote:

> Can anyone explain the logic behind the behavior of list slicing with
> negative strides?  For example:
> 
>   >>> print range(10)[:-3:-1]
>   [9,8]
> 
> I found this result very surprising, and would just like to see the
> rules written down somewhere.

Well, here is my attempt to emulate the algorithm. The trick seems to be to
substitute the start/stop parameters with 0 or length-1 depending on the
sign of step.

# no warranties!
def indices(length, start, stop, step):
    if step is None:
        step = 1
    if step < 0:
        if start is None:
            start = length-1
        elif start < 0:
            start += length

        if stop is None:
            stop = -1
        elif stop < 0:
            stop += length
    else:
        if start is None:
            start = 0
        elif start < 0:
            start += length

        if stop is None:
            stop = length
        elif stop < 0:
            stop += length

    if start > stop:
        while start > stop:
            yield start
            start += step
    else:
        while start < stop:
            yield start
            start += step

assert list(indices(10, None, -3, -1)) == range(10)[:-3:-1]
assert list(indices(10, None, -3, -2)) == range(10)[:-3:-2]
assert list(indices(10, 9, -3, -2)) == range(10)[9:-3:-2]
assert list(indices(10, None, None, None)) == range(10)[::]
assert list(indices(10, None, 5, 2)) == range(10)[:5:2]

I have to admit (late but better than never) that Raymond Hettinger's new
builtin reversed() has some merits:

>>> list(reversed(range(10)[-2:])) == range(10)[:-3:-1]
True

Peter




More information about the Python-list mailing list