Possible improvement to slice opperations.

Magnus Lycka lycka at carmen.se
Tue Sep 6 18:34:13 CEST 2005


Ron Adam wrote:
> Ok, lets see...  This shows the problem with using the gap indexing model.
> 
> L = range(10)
> 
> [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9  ]   # elements
> 0   1   2   3   4   5   6   7   8   9   10   # index's
> 
> L[3::1]  -> [3, 4, 5, 6, 7, 8, 9]  3rd index to end...  ok
> L[3:6:1] -> [3, 4, 5]  3rd index to 6th index... ok
> 
> L[3::-1] -> [3, 2, 1, 0]  4th index to beginning... umm
> L[6:3:-1] -> [6, 5, 4]  7th index to 4th index... ?
> 
> So negative strides use a different index position?
> 
>  [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9  ]   # elements
> -1   0   1   2   3   4   5   6   7   8   9    # index's
> 
> L[3::-1]  -> [3, 2, 1, 0]   3rd index to beginning... ok
> L[6:3:-1] -> [6, 5, 4]   6th index to 3rd index... ok

Ok, I see what you mean. The "view slices as indices standing
between the items in the sequence" model actually breaks down
with negative strides.

Then you need to view it more in the mathematical way of
half-open (or half-closed if you prefer) intervals.

[a,b) = { x | a <= x < b }

See http://en.wikipedia.org/wiki/Half-closed_interval

I still think the current sematics are the least surprising
though. For instance, if we want to implement a ring class
looking something like the one below, the logical way to do
that would allow it to be used as if it was a list.

Actually, such a ring class (extented to handle extended slices
correctly) would (I think) solve the tricky cases with things
such as l[0:-0] or l[9:-1:-1].

The complete implementation is left as an exercise to the
reader, although there's probably something like it in the
Python cookbook already.

class Ring(list):
     def __init__(self, size):
         self.size = size
     def __setitem__(self, i,v):
         return list.__setitem__(self, i%self.size, v)
     def __getitem__(self, i):
         return list.__getitem__(self, i%self.size)
     def __setslice__(self, i, j, v):
         return list.__setslice__(self, i%self.size, j%self.size,v)
     def __getslice__(self, i, j):
         return list.__getslice__(self, i%self.size, j%self.size)



More information about the Python-list mailing list