[Python-Dev] extended slicing for lists

Michael Hudson mwh21@cam.ac.uk
30 Jul 2000 17:14:51 +0100


Ka-Ping Yee <ping@lfw.org> writes:

> Hey, wait a second.  To get l[start:end:step], you start with 'start'
> and keep adding 'step' until you get to -- but not including -- 'end',
> right?  So l[len(l)-1:-1:-1] should return the entire list reversed,
> not the empty list.

Yes, but "-1" also means the last element of the list, so 

>>> range(10)[3:-1:2]
[3, 5, 7]

If you want "to the end" behaviour, use None (or nothing):

>>> range(10)[5::-2]
[5, 3, 1]
>>> range(10)[5:None:-2]
[5, 3, 1]

(these two are indistinguishable)

Also, can I plead my case in that this was not my decision - it's the
logic implemented by PySlice_GetIndices.

> range() demonstrates the behaviour nicely:
> 
>     >>> size = 5
>     >>> range(size-1,-1,-1)
>     [4, 3, 2, 1, 0]
> 
> Wouldn't l[sys.maxint:0:-1] return all but the first element of l in
> reverse order?

Yes.

>     >>> range(size-1,0,-1)
>     [4, 3, 2, 1]
> 
> Note that we should deprecate the use of sys.maxint (preferring None)
> in this situation, since if the step is less than -1, the elements
> you get ought to depend on the value of sys.maxint % step.  I'd expect:
> 
>     >>> l = [0, 1, 2, 3, 4, 5]
>     >>> l[5:0:-3]
>     [5, 2]
>     >>> l[6:0:-3]
>     [4, 1]
>     >>> l[7:0:-3]
>     [3, 0]
>     >>> l[8:0:-3]
>     [5, 2]

Whereas at the moment you get:

  >>> l[5:0:-3]
  [5, 2]
  >>> l[6:0:-3]
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  TypeError: slice indices must be integers
  >>> l[7:0:-3]
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  TypeError: slice indices must be integers
  >>> l[8:0:-3]
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  TypeError: slice indices must be integers

(which is definitely screwy).  Perhaps I shouldn't use
PySlice_GetIndices (but then if I don't use it for this patch, what on
earth would you use it for?).

At any rate PySlice_GetIndices needs mending to accept longs (in the
style of PyObject_GetItem).

> hence
> 
>     >>> l[sys.maxint:0:-3]
>     [???, ???]                     # depends on sys.maxint % 3
> 
> My guiding principle is that the indices should always match what
> you get from range(), and if start or end are missing, you get the
> items you would have gotten if you extend the sequence out forever.

Aside from the interpretation of negative indices, I basically agree.

Cheers,
M.

-- 
  languages shape the way we think, or don't.
                                        -- Erik Naggum, comp.lang.lisp