[Python-Dev] Slicing
Michael Hudson
mwh@python.net
19 Jun 2002 11:09:24 +0100
"David Abrahams" <david.abrahams@rcn.com> writes:
> 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?
No. The time machine has got you here; update to CVS and try again.
This comes down to the (slightly odd, IMHO) distinction between
sequences and mappings, which doesn't really appear at the Python
level.
type_pointer->tp_as_sequence->sq_item
takes a single int as a parameter
type_pointer->tp_as_mapping->mp_subscr
takes a PyObject*. Builtin sequences (as of last week) have mp_subscr
methods that handle slices. I haven't checked, but would be amazed if
PyObject_GetItem can't now be used with sliceobjects.
(PS: I'm not sure I've got all the field names right here. They're
close).
> 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
This area is very messy.
> 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
This last one is easy: you're trying to subscript the class 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?
You can't do this logic from Python, AFAIK. I think PyObject_GetItem
is your best bet.
Cheers,
M.
--
The only problem with Microsoft is they just have no taste.
-- Steve Jobs, (From _Triumph of the Nerds_ PBS special)
and quoted by Aahz Maruch on comp.lang.python