Negative array indicies and slice()

Robert Kern robert.kern at gmail.com
Thu Nov 1 12:13:48 CET 2012


On 10/31/12 8:16 PM, Andrew Robinson wrote:
> On 10/31/2012 02:20 PM, Ian Kelly wrote:
>> On Wed, Oct 31, 2012 at 7:42 AM, Andrew Robinson wrote:
>>
>>     Then; I'd note:  The non-goofy purpose of slice is to hold three data
>>     values;  They are either numbers or None.  These *normally* encountered
>>     values can't create a memory loop.
>>     So, FOR AS LONG, as the object representing slice does not contain an
>>     explicit GC pair; I move that we mandate (yes, in the current python
>>     implementation, even as a *fix*) that its named members may not be
>>     assigned any objects other than None or numbers....
>>
>>     eg: Lists would be forbidden....
>>
>>     Since functions, and subclasses, can be test evaluated by int(
>>     the_thing_to_try ) and *[] can too,
>>     generality need not be lost for generating nothing or numbers.
>>
>>
>> PEP 357 requires that anything implementing the __index__ special method be
>> allowed for slicing sequences (and also that __index__ be used for the
>> conversion).  For the most part, that includes ints and numpy integer types,
>> but other code could be doing esoteric things with it.
>
> I missed something... (but then that's why we're still talking about it...)
>
> Reading the PEP, it notes that *only* integers (or longs) are permitted in slice
> syntax.
> (Overlooking None, of course... which is strange...)
>
> The PEP gives the only exceptions as objects with method "__index__".
>
> Automatically, then, an empty list is forbidden (in slice syntax).
> However,  What you did, was circumvent the PEP by passing an empty list directly
> to slice(), and avoiding running it through slice syntax processing.

Why do you think it is forbidden by the syntax?

[~]
|1> class A(object):
..>     def __getitem__(self, key):
..>         return key
..>

[~]
|2> a = A()

[~]
|3> a[[]:]
slice([], None, None)


The PEP is a little unclear and refers to a state of the Python interpreter that 
no longer exists. At the time, I think __getslice__() was still not deprecated, 
and it did require ints (or after the PEP, __index__able objects). 
__getslice__() is now deprecated in favor of __getitem__() where you can 
interpret slice objects with arbitrary objects to your heart's content. 
Arbitrary objects *are* definitely allowed by the slice syntax (how could the 
syntax know what is an int and what is another kind of object?). Most objects 
that interpret slices, especially the builtin sequence types, do require 
__index__able objects (or None).

> So, what's the psychology behind allowing slice() to hold objects which are not
> converted to ints/longs in the first place?

In numpy, we (ab)use this freedom for some convenient notation in special 
objects. We have a couple of grid-making convenience objects:

[~]
|5> numpy.mgrid[1.5:2.5:0.1]
array([ 1.5,  1.6,  1.7,  1.8,  1.9,  2. ,  2.1,  2.2,  2.3,  2.4])


This syntax uses the start:stop:step notation to make a float range. If we use 
an imaginary integer in the "step" slot, mgrid will interpret it as the number 
of items requested instead of the step.

[~]
|6> numpy.mgrid[1.5:2.5:11j]
array([ 1.5,  1.6,  1.7,  1.8,  1.9,  2. ,  2.1,  2.2,  2.3,  2.4,  2.5])

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco



More information about the Python-list mailing list