views:

336

answers:

3

I don't understand the following part of the Python docs:

http://docs.python.org/reference/expressions.html#slicings

Is this referring to list slicing ( x=[1,2,3,4]; x[0:2] )..? Particularly the parts referring to ellipsis..

slice_item       ::=  expression | proper_slice | ellipsis

The conversion of a slice item that is an expression is that expression. The conversion of an ellipsis slice item is the built-in Ellipsis object.

+6  A: 

What happens is this. See http://docs.python.org/reference/datamodel.html#types and http://docs.python.org/library/functions.html#slice

Slice objects are used to represent slices when extended slice syntax is used. This is a slice using two colons, or multiple slices or ellipses separated by commas, e.g., a[i:j:step], a[i:j, k:l], or a[..., i:j]. They are also created by the built-in slice() function.

Special read-only attributes: start is the lower bound; stop is the upper bound; step is the step value; each is None if omitted. These attributes can have any type.

x=[1,2,3,4]
x[0:2]

The "0:2" is transformed into a Slice object with start of 0, stop of 2 and a step of None.

This Slice object is provided to x's __getitem__ method of classes you define.

>>> class MyClass( object ):
    def __getitem__( self, key ):
     print type(key), key


>>> x=MyClass()
>>> x[0:2]
<type 'slice'> slice(0, 2, None)

For the build-in list class, however, a special __getslice__ method must be overridden.

class MyList( list ):
    def __getslice__( self, i, j=None, k=None ):
        # decode various parts of the slice values

The ellipsis is a special "ignore this dimension" syntax provided to multi-dimensional slices.

Also see http://docs.python.org/library/itertools.html#itertools.islice for even more information.

S.Lott
+4  A: 

Defining simple test class that just prints what is being passed:

>>> class TestGetitem(object):
...   def __getitem__(self, item):
...     print type(item), item
... 
>>> t = TestGetitem()

Expression example:

>>> t[1]
<type 'int'> 1
>>> t[3-2]
<type 'int'> 1
>>> t['test']
<type 'str'> test
>>> t[t]
<class '__main__.TestGetitem'> <__main__.TestGetitem object at 0xb7e9bc4c>

Slice example:

>>> t[1:2]
<type 'slice'> slice(1, 2, None)
>>> t[1:'this':t]
<type 'slice'> slice(1, 'this', <__main__.TestGetitem object at 0xb7e9bc4c>)

Ellipsis example:

>>> t[...]
<type 'ellipsis'> Ellipsis

Tuple with ellipsis and slice:

>>> t[...,1:]
<type 'tuple'> (Ellipsis, slice(1, None, None))
nosklo
+3  A: 

Ellipsis is used mainly by the numeric python extension, which adds a multidementional array type. Since there are more than one dimensions, slicing becomes more complex than just a start and stop index; it is useful to be able to slice in multiple dimentions as well. eg, given a 4x4 array, the top left area would be defined by the slice "[:2,:2]"

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

>>> a[:2,:2]  # top left
array([[1, 2],
       [5, 6]])

Ellipsis is used here to indicate a placeholder for the rest of the array dimensions not specified. Think of it as indicating the full slice [:] for dimensions not specified, so for a 3d array, a[...,0] is the same as a[:,:,0] and for 4d, a[:,:,:,0].

Note that the actual Ellipsis literal (...) is not usable outside the slice syntax in python2, though there is a builtin Ellipsis object. This is what is meant by "The conversion of an ellipsis slice item is the built-in Ellipsis object." ie. "a[...]" is effectively sugar for "a[Ellipsis]". In python3, ... denotes Ellipsis anywhere, so you can write:

>>> ...
Ellipsis

If you're not using numpy, you can pretty much ignore all mention of Ellipsis. None of the builtin types use it, so really all you have to care about is that lists get passed a single slice object, that contains "start","stop" and "step" members. ie:

l[start:stop:step]   # proper_slice syntax from the docs you quote.

is equivalent to calling:

l.__getiem__(slice(start, stop, step))
Brian