[Python-ideas] Where did we go wrong with negative stride?
Tim Peters
tim.peters at gmail.com
Mon Oct 28 19:49:12 CET 2013
...
[Tim]
>> "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.
[Steven D'Aprano]
> 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.
As a Python implementer, _I_ do, but not as a user. As Guido noted,
under the proposal we have:
s[i:j:k] == s[i:j][::k]
That should (finally?) make it crystal clear that applying the stride
has nothing directly to do with the indices of the selected elements
in the original sequence (`s`). In the RHS's "[::k]", all knowledge
of s's indices has been lost. If _you_ want to think of it in terms
of indices into `s`, that's fine, and the implementation obviously
needs to index into `s` to produce the result, but a user can just
think "OK! start at the start and take every k'th element
thereafter". As in, e.g., the sieve of Eratosthenes: "search right
until you find the first integer not yet crossed out. Call it p.
Then cross out every p'th integer following. Repeat." There's no
reference made to "indices" there, and none needed in the mental
model. An implementation using an array or list will need to know the
index of p, but that's it. If that index is `i`, then, e.g.,
array_or_list[i+p: :p] = [False] * len(range(i+p, len(array_or_list), p))
faithfully translates the rest.
[...]
>>> 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?
No. I do wonder whether negative strides have been "an attractive
nuisance" overall, but guess they'd be more "attractive" than
"nuisance" under the proposal.
[...]
>>> 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.
OK. Then use a positive stride ;-)
> 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.
Good idea! I made only one real use of non-trivial negative strides,
that I can recall, in the last year:
# nw index is n-1+i-j
# in row i, that's n-1+i thru n-1+i-(n-1) = i
# the leftmost is irrelevant, so n-1+i-1 = n-2+i thru i
# ne index is i+j
# in row i, that's i thru i+n-1
# the rightmost is irrelevant, so i thru i+n-2
assert nw[n-1+i] == 0
assert ne[i+n-1] == 0
codes = [0] * (3*n - 2)
codes[0::3] = up
codes[1::3] = ne[i: n-1+i]
codes[2::3] = nw[n-2+i: i-1: -1] # here
That was excruciating to get right. Curiously, the required `ne` and
'nw` index sets turned out to be exactly the same, but _end up_
looking different in that code because of the extra fiddling needed to
deal with that the required 'nw` index _sequence_ (as opposed to the
index set) is the reverse of the required `ne` index sequence. Under
the proposal, the last line would be written:
codes[2::3] = nw[i: n-1+i: -1]
instead, making it obvious at a glance that the the 'nw` index
sequence is the reverse of the `ne` index sequence.
And that's all the empirical proof I need - LOL ;-)
> ...
More information about the Python-ideas
mailing list