Slice inconsistency?

Terry Reedy tjreedy at udel.edu
Sat Sep 27 12:56:25 EDT 2003


"Stephen Horne" <$$$$$$$$$$$$$$$$$@$$$$$$$$$$$$$$$$$$$$.co.uk> wrote
in message news:bqeanvgel9ra3va44j090bmn2l126t340g at 4ax.com...
> On Fri, 26 Sep 2003 17:28:02 -0400, "Terry Reedy" <tjreedy at udel.edu>
> wrote:
> >A square-bracketed subscript (index/key) is a *single* object, in
this
> >case a tuple.  The contents of the tuple are irrelevant (for this
> >code).  Any  tuple will be echoed:
>
> I didn't see any sign that he wasn't aware of that.

Since you both missed the key points I tried to make, I will try be a
little clearer by being much wordier.

When a sequence is indexed with a slice expression, the interpreter
tries to immediately slice it.  From 2.2.1:

>>> def f1(): return c[:-1]
...
>>> dis.dis(f)
          0 SET_LINENO               1

          3 SET_LINENO               1
          6 LOAD_GLOBAL              0 (c)
          9 LOAD_CONST               1 (-1)
         12 SLICE+2
         13 RETURN_VALUE

No intermediate slice object is even constructed.  Since stop is
negative, 'SLICE+2' must look up the length to do the subtraction.

When the index is a tuple, the interpreter does not try to slice:

>>> def f2(): return c[:1,:1]
...
>>> dis.dis(f2)
          0 SET_LINENO               1
          3 SET_LINENO               1
          6 LOAD_GLOBAL              0 (c)
          9 LOAD_CONST               0 (None)
         12 LOAD_CONST               1 (1)
         15 BUILD_SLICE              2
         18 LOAD_CONST               0 (None)
         21 LOAD_CONST               1 (1)
         24 BUILD_SLICE              2
         27 BUILD_TUPLE              2
         30 BINARY_SUBSCR
         31 RETURN_VALUE

For BINARY_SUBSCR, the contents of the tuple only matter when the
tuple is hashed.  Roberto prevented this with his custom __getitem__()
method.  Since slices do not hash, a tuple of slices is normally
useless and would give a TypeError if hashing were attempted.

> I would have expected, given that the tuple contains slice objects
> constructed from the multiple-slice notation, that the same
> translations would be performed on the slices that are inserted into
> the tuple that are applied when the single slice is created.

Slice objects and tuples thereof were added for use by Numerical
Python so it could slice multidimensional arrays stored as a single
linear array.  The length used for start or stop subtraction is the
length of each dimension, which is typically different for each
dimension.  Subtracting the total length is the *wrong* thing to do
for multiple slices.  Only custom code can know the correct factors of
that total length to use for each component slice.

In Roberto's example, there is no single slice created.  See
disassembly above and comment below.

> That is, whether the single or multiple notation is used, and
whether
> the slice objects are placed in a tuple or not, they are constructed
> from the tuple notation

Sorry, wrong.  Tuple notation for single slices givea a different
result.

>>> c[:-1] # this is *NOT* tuple notation
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: C instance has no attribute '__len__'

>>> c[:-1,] #
<type 'tuple'> (slice(None, -1, None),)

DING!  Here is how to get consistency.  Add the tuplizing comma.

Terry J. Reedy






More information about the Python-list mailing list