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