Negative array indicies and slice()

Andrew Robinson andrew3 at r3dsolutions.com
Mon Oct 29 14:00:08 EDT 2012


On 10/29/2012 06:53 AM, Chris Angelico wrote:
> Can you provide links to these notes? I'm looking at
> cpython/Include/sliceobject.h that has this comment:
>
> /*
>
> A slice object containing start, stop, and step data members (the
> names are from range).  After much talk with Guido, it was decided to
> let these be any arbitrary python type.  Py_None stands for omitted values.
> */
>
> Also, the code for slice objects in CPython works with Py_ssize_t (a
> signed quantity of the same length as size_t), which will allow at
> least 2**31 for an index. I would guess that your crashes were nothing
> to do with 20 million elements and slices.
>
> ChrisA
Let's look at the source code rather than the web notes -- the source 
must be the true answer anyhow.

I downloaded the source code for python 3.3.0, as the tbz;
In the directory "Python-3.3.0/Python", look at Python-ast.c, line 2089 
& ff.

Clearly a slice is malloced for a slice_ty type.
It has four elements: kind, lower, upper, and step.

So, tracing it back to the struct definition...

"Include/Python-ast.h"  has "typedef struct _slice *slice_ty;"

And, here's the answer!:

enum _slice_kind {Slice_kind=1, ExtSlice_kind=2, Index_kind=3};
struct _slice {
         enum _slice_kind kind;
         union {
                 struct {
                         expr_ty lower;
                         expr_ty upper;
                         expr_ty step;
                 } Slice;

                 struct {
                         asdl_seq *dims;
                 } ExtSlice;

                 struct {
                         expr_ty value;
                 } Index;

         } v;
};


So, slice() does indeed have arbitrary python types included in it; 
contrary to what I read elsewhere.
expr_ty is a pointer to an arbitrary expression, so the actual structure 
is 4 pointers, at 32 bits each = 16 bytes.
The size of the structure itself, given in an earlier post, is 20 bytes 
-- which means one more pointer is involved, perhaps the one pointing to 
the slice structure itself.

Hmm...!

An empty tuple gives sys.getsizeof( () ) = 24.

But, I would expect a tuple to be merely a list of object pointers; 
hence I would expect 4 bytes for len(), and then a head pointer 4 bytes, 
and then a pointer for each object.
3 objects gives 12 bytes, + 8 = 16 bytes.

Then we need one more pointer so Python knows where the struct is...
So a Tuple of 3 objects ought to fit nicely into 20 bytes; the same size 
as slice() --

but it's 24, even when empty...
And 36 when initialized...
What are the extra 16 bytes for?

All I see is:
typedef struct { object** whatever } PyTupleObject;










More information about the Python-list mailing list