[Tutor] 'slice', etc

eryksun eryksun at gmail.com
Sat Dec 7 03:22:16 CET 2013


On Fri, Dec 6, 2013 at 10:39 AM, spir <denis.spir at gmail.com> wrote:
>
> How does slicing in Python really work? Apparently, there are slice objects
> (start, past-end, step), generated using either the 'slice' builtin func or
> the extended slicing syntax [i:k:s]. Is this correct? [1]

Have you read the docs for the data model? Slice objects are described
in section 3.2, a bit before section 3.3:

http://docs.python.org/3/reference/datamodel.html

> Does (only) the extended syntax (always) trigger slicing instead of
> contructing a new subsequence? (new substring or sublist or whatever,
> actually holding a section of the original sequence)

What __getitem__ returns for a slice is at the disgression of the
programmer. For example, slicing a list returns a new list, while
slicing a NumPy array returns a view of the original array:

    >>> import numpy as np
    >>> a1 = np.arange(5)
    >>> a2 = a1[2:]

    >>> a1.flags.owndata
    True
    >>> a2.flags.owndata
    False
    >>> a2.base is a1
    True

FYI, before the introduction of slice objects, Python used
__getslice__, __setslice__, and __delslice__. These methods are
deprecated in 2.x and removed from 3.x. For the most part you can
ignore this bit of cruft in 2.x, but it's an issue if you're extending
types that implement the old interface.

2.x example:

    class Test(object):

        def __getslice__(self, i, j):
            return '__getslice__', i, j

        def __getitem__(self, key):
            return  '__getitem__', key


    >>> list(sys.version_info)
    [2, 7, 5, 'final', 0]

    >>> t = Test()

    >>> t[5:10]
    ('__getslice__', 5, 10)

    >>> t[5:10:2]
    ('__getitem__', slice(5, 10, 2))

If __getslice__ is implemented, it's only used with integer indexes.
If the index values aren't integers or lack an __index__ method, the
interpreter creates a slice object and calls __getitem__.

    class Index(object):

        def __init__(self, v):
            self._v = v

        def __index__(self):
            return self._v


    >>> t[Index(5):Index(10)]
    ('__getslice__', 5, 10)

    >>> t['a':'b']
    ('__getitem__', slice('a', 'b', None))


More information about the Tutor mailing list