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

Steven D'Aprano steve at pearwood.info
Mon Oct 28 13:09:21 CET 2013


On Sun, Oct 27, 2013 at 10:05:11PM -0500, Tim Peters wrote:
> ]Steven D'Aprano <steve at pearwood.info>]
> > ...
> > I really like that view point, but it has a major problem. As
> > beautifully elegant as the "cut between positions" model is for
> > stride=1, it doesn't extend to non-unit strides. You cannot think about
> > non-contiguous slices in terms of a pair of cuts at position <start> and
> > <end>. I believe that the cleanest way to understand non-contiguous
> > slices with stride > 1 is to think of array indices. That same model
> > works for the negative stride case too.
> 
> "Cut between positions" in my view has nothing to do with the stride.
> It's used to determine the portion of the sequence _to which_ the
> stride applies.  From that portion, we take the first element, the
> first + |stride|'th element, the first + |stride|*2'th element, and so
> on.  Finally, if stride < 0, we reverse that sequence.  That's the
> proposal.  It's simple and uniform.

That's quite a nice model, and I can't really say I dislike it. But it 
fails to address your stated complaint about the current behaviour, 
namely that it forces the user to think about array indexing instead of 
cutting between elements. No matter what we do, we still have to think 
about array indexes.


> > But that's just a longer way of writing this:
> >
> >     s[1:8:2] => s[1] + s[3] + s[5] + s[7]
> >     => 'bdfh'
> >
> > which I maintain is a cleaner way to think about non-unit step-sizes.
> 
> As above, so do I.  start:stop just delineates the subsequence to
> which the stride applies.

That's the part that was unclear to me from your earlier post.


[...]
> > In other words, you want negative strides to just mean "reverse the
> > slice"
> 
> If they're given a ;meaning at all.

Is this a serious proposal to prohibit negative slices?


[...]
> > One consequence of this proposed change is that the <start> parameter is
> > no longer always the first element returned. Sometimes <start> will be
> > last rather than first. That disturbs me.
> 
> ?  <start> is always the first element of the subsequence to which the
> stride is applied.  If the stride is negative, then yes, of course the
> first element of the source subsequence would be the last element of
> the returned subsequence.

Right. And that's exactly what I dislike about the proposal.


I have a couple of range-like or slice-like functions which take 
start/stop/stride arguments. I think I'll modify them to have your 
suggested semantics and see how well they work in practice. But in the 
meantime, here are my tentative votes:

-1 on prohibiting negative strides altogether. They're useful.

-1 on deprecating negative strides, for temporary removal, followed by 
reintroduce them again in the future with different semantics. If I'm 
going to be forced to change my code to deal with this, I want to only 
do it once, not twice.

+0 on introducing a __future__ directive to change the semantics of 
negative strides (presumably in Python 3.5, since 3.4 feature-freeze is 
so close), with the expectation that it will probably become the default 
in 3.6 or 3.7.

+0.5 on the status quo.



-- 
Steven


More information about the Python-ideas mailing list