number ranges (was Re: Matlab page on scipy wiki)
Tim Hochberg
tim.hochberg at ieee.org
Mon Feb 20 11:13:44 EST 2006
bonono at gmail.com wrote:
> Tim Hochberg wrote:
>
>>Colin J. Williams wrote:
>>
>>
>>>>It would be good if the range and slice could be merged in some way,
>>>>although the extended slice is rather complicated - I don't understand it.
>>>>
>>>> The semantics for an extended slicing are as follows. The primary
>>>> must evaluate to a mapping object, and it is indexed with a key that
>>>> is constructed from the slice list, as follows. If the slice list
>>>> contains at least one comma, the key is a tuple containing the
>>>> conversion of the slice items; otherwise, the conversion of the lone
>>>> slice item is the key. 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. The conversion of a proper
>>>> slice is a slice object (see section section 4.2 The standard type
>>>> hierarchy <http://www.network-theory.co.uk/docs/pylang/ref_30.html>)
>>>> whose |start|, |stop| and |step| attributes are the values of the
>>>> expressions given as lower bound, upper bound and stride,
>>>> respectively, substituting |None| for missing expressions.
>>>>
>>>>[source: http://www.network-theory.co.uk/docs/pylang/ref_60.html]
>>>>
>>>>The seems to be a bit of a problem with slicing that needs sorting out.
>>>>
>>>>The syntax for a slice list appears to allow multiple slices in a list:
>>>>
>>>> extended_slicing ::= primary <primaries.html#tok-primary> "["
>>>> slice_list <slicings.html#tok-slice_list> "]"
>>>> slice_list ::= slice_item <slicings.html#tok-slice_item> (","
>>>> slice_item <slicings.html#tok-slice_item>)* [","]
>>>>
>>>>but the current interpreter reports an error:
>>>>
>>>> >>> a= range(20)
>>>> >>> a[slice(3, 9, 2)]
>>>> [3, 5, 7]
>>>> >>> a[slice(3, 9, 2), slice(5, 10)]
>>>> Traceback (most recent call last):
>>>> File "<interactive input>", line 1, in ?
>>>> TypeError: list indices must be integers
>>>> >>>
>>>>
>>Extended slicing has nothing to do with lists. All that gobbeldy gook is
>>trying to tell you is what the interpreter does with O[1:2:3, 4:5:6]
>>where O is some arbitrary object. What it does is:
>>
>>O[1:2:3, 4:5:6] == O[slice(1,2,3), slice(4,5,6)]
>> == O.__getitem__((slice(1,2,3), slice(4,5,6)))
>>
>>In the case of python lists, __getitem__ doesn't support multiple slice
>>arguments. However, you are free to define your own types which do
>>support multiple slices.
>>
>
> That explains it but the current documentation in the reference manual
> doesn't(I also tried what Colin did when reading that part). And as I
> mentioned in another post, the current documentation suggests that
> extended slicing is not supported for sequence type. As it said the
> primary must be evaluated to mapping object for extended slicing.
> Though it seems it doesn't matter as all python does now is turn
> [start:stop:stride] into slice object and pass that to __getitem__, no
> matter what object it is.
I try not to read the reference manual, since it just makes my eyes
glaze over, but I believe that the distinction between sequences and
mappings referred to only exists for objects defined at the C level.
Objects can define getitem two different ways: using sq_item/sq_slice or
using mp_subscript. The former functions take integers, the latter takes
general PyObjects. So, only the mapping version (mp_*) supports extended
slicing. Python class objects always have the mp_subscript defined and
it dispatches things to __getitem__.
In the past, lists only supported start and stop arguments to slices, so
they could get by with using the sq_ functions. Now that they support
step arguments as well, it seems that they must define the mapping
methods as well, although I admit I haven't checked.
You can get an idea of what sq_slice does by looking at the following
chunk of code:
class ExtendedSlicingDemo(object):
def __getitem__(self, key):
return key
def __getslice__(self, start, stop):
return start, stop
esd = ExtendedSlicingDemo()
print esd[1:2]
print esd[1:2:3]
print esd[1:2:3, 3:4:5]
print esd[1:2:3, ..., 3:4:5]
#....
Note that __getslice__ is deprecated. I think sq_item/sq_slice is still
around for efficiency reasons for sequences that don't support extended
slicing as well as backwards compatibility / historical reasons.
-tim
More information about the Python-list
mailing list