[Python-Dev] Slicing

David Abrahams David Abrahams" <david.abrahams@rcn.com
Tue, 18 Jun 2002 14:21:23 -0400


I did a little experiment to see if I could use a uniform interface for
slicing (from C++):

>>> range(10)[slice(3,5)]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: sequence index must be integer
>>> class Y(object):
...     def __getslice__(self, a, b):
...             print "getslice",a,b
...
>>> y = Y()
>>> y[slice(3,5)]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsubscriptable object
>>> y[3:5]
getslice 3 5

This seems to indicate that I can't, in general, pass a slice object to
PyObject_GetItem in order to do slicing.** Correct?

So I went looking around for alternatives to PyObject_GetItem. I found
PySequence_GetSlice, but that takes int parameters, and AFAIK there's no
rule saying you can't slice on strings, for example.

Further experiments revealed:

>>> y['hi':'there']
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsubscriptable object
>>> class X(object):
...     def __getitem__(self, x):
...             print 'getitem',x
...
>>> X()['hi':'there']
getitem slice('hi', 'there', None)

So I /can/ slice on strings, but only through __getitem__(). And...

>>> class Z(Y):
...     def __getitem__(self, x):
...             print 'getitem',x
...
>>> Z()[3:5]
getslice 3 5
>>> Z()['3':5]
getitem slice('3', 5, None)

So Python is doing some dispatching internally based on the types of the
slice elements, but:

>>> class subint(int): pass
...
>>> subint()
0
>>> Z[subint():5]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsubscriptable object

So it's looking at the concrete type of the slice elements. I'm not sure I
actually understand how this one fails.

I want to make a generalized getslice function in C which can operate on a
triple of arbitrary objects. Here's the python version I came up with:

    def getslice(x,start,finish):
        if (type(start) is type(finish) is int
            and hasattr(type(x), '__getslice__')):
            return x.__getslice__(start, finish)
        else:
            return x.__getitem__(slice(start,finish))

Have I got the logic right here?

Thanks,
Dave


**it seems like a good idea to make it work in the Python core, by
recognizing slice objects and dispatching the elements to __getslice__ if
they are ints and if one is defined. Have I overlooked something?

+---------------------------------------------------------------+
                  David Abrahams
      C++ Booster (http://www.boost.org)               O__  ==
      Pythonista (http://www.python.org)              c/ /'_ ==
  resume: http://users.rcn.com/abrahams/resume.html  (*) \(*) ==
          email: david.abrahams@rcn.com
+---------------------------------------------------------------+