[Tutor] extended slicings

David Ascher da@ski.org
Tue, 18 May 1999 11:39:29 -0700 (Pacific Daylight Time)


On Wed, 12 May 1999 Christian.Schaller@atd.mchh.siemens.de wrote:

>   Just a dull question: how are extended slicings used?  The Python Ref
> (pp30) just says it is used with mapping objects.  Can you please give me an
> example?

The only known use of extended slicing (at least known to me =) is the
Numeric Python array slicing.  By extended slicing I refer to the ::
notation (a[1:10:2]).

Here's how slicing works in general -- it depends on what's inside the
[]'s.  Let's setup a test class to tell us what it's doing:

>>> class TestClass:
...   def __getitem__(self, item):
...     print "__getitem__ with", item
...   def __getslice__(self, start, end):
...     print "__getslice__ with", start, end
...

and we'll create an instance of this:

>>> thing = TestClass()

Now, if there's only one thing in the [] (no :'s), then __getitem__ is
called, with the "thing" being the argument to __getitem__:

>>> thing[1]
__getitem__ with 1

If there are two things separated by a :, then the __getslice__ call is
invoked, with the two arguments:

>>> thing[1:3]
__getslice__ with 1 3

If the "end" of the slice is omitted, then sys.maxint is the second
argument:

>>> thing[1:]
__getslice__ with 1 2147483647

if the "beginning" of the slice is omitted, then 0 is the first argument:

>>> thing[:4]
__getslice__ with 0 4

This is all standard and used all over the place.  For extended slicing,
things are a little odder -- when three arguments (two :'s) are used, then
__getitem__ is called with a slice object as the sole argument.  That
slice object is a new kind of Python object (recently introduced in the
bestiary of types), which has a "constructor" slice() builtin, and has
three attributes (start, stop, step).

To test it:

>>> thing[1:10:2]
__getitem__ with slice(1, 10, 2)

This is the same as

>>> thing[slice(1,10,2)]
__getitem__ with slice(1, 10, 2)

Examining just what these 'slice' objects are:

>>> sampleslice = slice(1,10,2)
>>> sampleslice
slice(1, 10, 2)
>>> dir(sampleslice)
['start', 'step', 'stop']
>>> sampleslice.start
1
>>> sampleslice.step
2
>>> sampleslice.stop
10

What about when some of the "arguments" to the slice are omitted?

>>> thing[:10:2]
__getitem__ with slice(None, 10, 2)
>>> thing[1::2]
__getitem__ with slice(1, None, 2)
>>> thing[1:10:]
__getitem__ with slice(1, 10, None)
>>> thing[::]
__getitem__ with slice(None, None, None)

In other words, omitted arguments are replaced with None.  This is
different from the slice behavior (and IMHO better).

What extended slicing *does* is up to the object, just like for all of the
__special__ calls.  You can tell from the names of the attributes of slice
objects that the motivating notion for them was to define a stepsize, or a
stride, of a range.  But that's up to you, the programmer, to decide.

--david ascher