[Python-Dev] PEP 203 Augmented Assignment

Ka-Ping Yee ping@lfw.org
Thu, 27 Jul 2000 10:25:38 -0700 (PDT)

On Thu, 27 Jul 2000, Guido van Rossum wrote:
> I suppose we could inspect the __getslice__ method's argument count
> (it *is* available somewher) but that seems a hack (and could still
> break if default arguments were used for something else).


> Another solution: require a class variable to indicate the class's
> awareness: e.g. you must define __getslice_takes_three_args__ when
> __getslice__(lo, hi, step) is supported, otherwise the call goes to
> __getitem__(slice(lo, hi, step)).

Here's another solution: if you're going to revamp the whole
item/slice-getting interface, which is what this pretty much amounts
to, use a separate interface.

Old interface:

    __getitem__(index)               # I get an ITEM.
    __getitem__(slice-object)        # I get a SLICE or an ITEM. (!)
    __getslice__(lo, hi, step)       # I get a SLICE.

New interface:
    __get__(index)                   # I get an ITEM.
    __get__(slice-object)            # I get a SLICE or an ITEM. (!)

To be honest, the whole collision between slices and items makes
me rather uncomfortable.  I would prefer to separate them: one
method for getting *items*, one method for getting *slices*.
Neither of the interfaces above handles this correctly for the
case of multidimensional arrays.  So, how about:

    __get__(index, ...)              # I want an ITEM.
    __getslice__(slice-object, ...)  # I want a SLICE.

I think an interface like this would be much easier to program
against.  The return value is better defined: __get__ always
returns a single item; __getslice__ always returns some kind of
collection of items (usually, if not always, the same type as
the original collection being sliced).

This would require detection of whether any of the components
of a multidimensional (i.e. tuple) index were slices, but i
think the improved consistency is well worth it.  __getslice__
is called if any slices are involved; __get__ is called otherwise.

Here are some examples for illustration:

    a[i]           a.__get__(i)
    a[i, j]        a.__get__(i, j)

    a[i:j]         a.__getslice__(slice(i, j))
    a[i:j:k]       a.__getslice__(slice(i, j, k))

    a[i, j, k]     a.__get__(i, j, k)
    a[i, j, k:l]   a.__getslice__(i, j, slice(k, l))

I can't imagine ever wanting to define custom behaviour for
__getslice__ *without* implementing __get__ or __getitem__,
so the presence of a __get__ method can be used to detect
whether we should use the new interface.

-- ?!ng