On 10/29/2013 05:07 PM, Nick Coghlan wrote:
On 30 Oct 2013 07:26, "Ron Adam" <ron3200@gmail.com
I think it may be the only way to get a clean model of slicing from both directions with a 0 based index system.
Isn't all that is needed to prevent the default wraparound behaviour clamping negative numbers to zero on input?
Well, you can't have indexing from the other end and clamp index's to zero at the same time. The three situations are... index both i and j from the front index both i and j from the end index i from the front + index j from the end. (?) And then there is this one, which is what confuses everyone. index i from the end + index j from the front. It's useful in the current slice semantics where I and J are swapped if K is negative. It works, but is not easy to think about clearly. It's meant to match up with start and stop concepts, rather than left and right. Another issue is weather or not a slice should raise an Index error if it's range is outside the length of the sequence. Both behaviours are useful. Currently it doesn't on one end and give the wrong output on the other. (When moving a slice left or right.) :-/ For that matter the wraparound behaviour is sometimes useful too. But not if it's only on the left side. And then there's the idea of open a closed ends. Which you have an interest in. Assuming their is four combinations of that... both-closed, left-open, right-open, and both-open. That's a lot of things to be trying to shove into one syntax! So it seems (to me) we may be better off to just concentrate on writing some functions with the desired behaviour(s) and leaving the slice syntax question to later. (But I'm very glad these things are being addressed.) A function that would cover nearly all of the use cases I can think of... # Get items that are within slice range. # index's: l, r, rl, rr --> left, right, rev-left, rev-right # The index's always use positive numbers. # step and width can be either positive or negative. # width - chunk to take at each step. (If it can work cleanly.) get_slice(obj, l=None, r=None, ri=None, rr=None, step=1, width=1) Used as... a = get_slice(s, l=i, r=j) # index from left end a = get_slice(s, rl=i, rr=j) # index from right end a = get_slice(s, l=i, rr=j) # index from both ends While that signature definition is long and not too pretty, it could be wrapped to make more specialised and nicer to use variations. Or it could be hidden away in __getitem__ methods. def mid_slice(obj, i, j, k): """Slice obj i and j distance from ends.""" return get_slice(obj, l=i, rr=j, step=k) Instead of using flags for these... "closed" "open" "open-right" "open-left" "reversed" "raise-err" "wrap-around" Would it be possible to have those applied with a context manager while the object is being indexed? with index_mode(seq, "open", "reversed") as s: r = mid_slice(s, i, j) That could work with any slice syntax we use later. And makes a nice building block for creating specialised slice functions.
As in:
def clampleft(start, stop, step): if start is not None and start < 0: start = 0 if stop is not None and stop < 0: stop = 0 return slice(start, stop, step)
Similar to rslice and "reverse=False", this could be implemented as a "range=False" flag (the rationale for the flag name is that in "range", negative numbers are just negative numbers, without the wraparound behaviour normally exhibited by the indices calculation in slice objects).
I know some have mentioned unifying range and slice, even though they aren't the same thing... But it suggests doing... seq[range(i,j,k)] I'm not sure there an any real advantage to that other than testing that range and slice behave in similar ways.
I think there are two reasonable options that could conceivably be included in 3.4 at this late stage:
* Make slice subclassable and ensure the C API and stdlib respect an overridden indices() method
I think that would be good, it would allow some experimentation that may be helpful. Is there any reason to not allow it?
* add a "reverse" flag to both slice and range, and a "range" flag to slice.
Either way, if any changes are going to be made, a PEP should be written up summarising some of the ideas in this thread, including the clampleft() and rslice() recipes that work in current versions of Python.
I agree. :-) Cheers, Ron