extended slicing and negative stop value problem

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Aug 20 16:40:01 EDT 2011

Pardon me for breaking threading, but I don't have Max's original post.

On Sat, Aug 20, 2011 at 7:20 PM, Max Moroz <maxmoroz at gmail.com> wrote:

> Would it be a good idea to change Python definition so that a[10, -1, -1]

I presume you mean slice notation a[10:-1:-1].

> referred to the elements starting with position 10, going down to the
> beginning?

No, almost certainly not. Such a change would break backwards compatibility,
and so would only be allowed under very unusual circumstances: the current
behaviour would have to be a major problem, or the new behaviour a huge
benefit, or both, to make up for:

(1) the extra work needed to change the behaviour (probably involving
a "from __future__ import ..." feature for the first version or two); 

(2) breaking people's existing code; and

(3) forcing people to learn the new behaviour and unlearn the old.

Even if the old behaviour is "wrong", the work needed to fix it may be more
than the benefit. If this was going to be "fixed", the time was probably
about three years ago, when Python3 was just starting. Now such a change
will probably need to wait for the hypothetical Python 4000.

> This would require disabling the "negative stop value means counting from
> the end of the array" magic whenever the step value is negative.

Which will hurt people who expect the current behaviour:

>>> a[8:-8:-1]
[8, 7, 6, 5, 4, 3]

> The reason for this idea is that many people (me including) try to use
> extended slices with negative step values, only to realize that they are
> messed up. For example, if your stop value is reduced in a loop from a
> positive number to -1, the behavior breaks whenever it hits -1.

Yes, negative step values are unintuitive, especially if the step is not -1.
The solution is, "Don't do that then!". 

The usual advice is to do your slicing twice, reversing it the second time:

# Instead of a[10:-1:-1], which looks like it should work, but doesn't.

(or use the reversed() built-in instead of the second slice), or to write a
helper function to adjust the indexes and get whatever behaviour you like.

>>> a[10:-11:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]


More information about the Python-list mailing list