[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