Negative array indicies and slice()

Robert Kern robert.kern at gmail.com
Fri Nov 2 06:48:50 EDT 2012


On 11/2/12 8:57 AM, Andrew Robinson wrote:
> Hi Ian,
>
> I apologize for trying your patience with the badly written code example.  All
> objects were meant to be ThirdParty(), the demo was only to show how a slice()
> filter could have been applied for the reasons PEP357 made index() to exist.
> eg: because numpy items passed to __getitems__ via slice syntax [::] were
> illegal values.
> PEP 357 is the one who specifically mentioned Numpy types -- which is the only
> reason I used the name in the example;  I could have just as well used a string.
>
> I am fully aware of what numpy does -- I have used it; modified the fortran
> interfaces underneath, etc.
>
> The index() method, however, affects *all* list objects in Python, not just
> Numpy's -- correct?

Please forget that PEP 357 mentions slices at all. The motivation for the 
__index__() method (not index()) goes far beyond slices. I'm not really sure why 
they are given such a prominent place in the PEP. Let me try to lay out the 
motivation more clearly.

numpy has objects that represent integers but cannot be subclasses of the Python 
int or long objects because their internal representations are different. These 
are the width-specific types: uint8, int16, int64, etc. Before __index__() was 
introduced, all indexing operations in the builtin Python sequence types 
strictly checked for int or long objects and rejected other objects. We wanted 
to provide a generic method that third party types could implement to say, "Yes, 
I really am an integer, here is my value in a canonical representation you can 
understand." We could not use __int__() for this purpose because it has 
additional semantics, namely conversion from not-integers to integers. This is 
why floats are mentioned; they do not generally represent integers but they do 
define an __int__() method for their conversion to ints via the floor() 
function. Generally, they should be rejected as indices. With the __index__() 
method, we have a solution: int16 and the rest get __index__() methods and float 
doesn't.

This is used where an integer index or offset is needed, not just in slices. 
List indices, file.seek(), mmap.mmap(), etc. The change to use PyIndex_Check() 
instead of PyInt_Check() was not very difficult or extensive. Even if you were 
to change the slicing API for your other reasons, __index__() would still be needed.

-- 
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