Bernhard
Bernhard

Reputation: 2251

Python - Basic vs extended slicing

When experimenting with slicing I noticed a strange behavior in Python 2.7:

class A:
    def __getitem__(self, i):
        print repr(i)
a=A()
a[:] #Prints slice(0, 9223372036854775807, None)
a[::] #prints slice(None, None, None)
a[:,:] #prints (slice(None, None, None), slice(None, None, None))

When using a single colon in the brackets, the slice object has 0 as start and a huge integer as end. However, when I use more than a single colon, start and stop are None if not specified.

Is this behaviour guaranteed or implementation specific?

The Documentation says that the second and third case are extended slicing, while the first case is not. However, I couldn't find any clear explanation of the difference between basic and extended slicing.

Are there any other "special cases" which I should be aware of when I override __getitem__ and want to accept extended slicing??

Upvotes: 9

Views: 424

Answers (1)

dhke
dhke

Reputation: 15398

For Python 2 [:] still calls __getslice__(self, i, j) (deprecated) and this is documented to return a slice slice(0, sys.maxsize, None) when called with default parameters:

Note that missing i or j in the slice expression are replaced by zero or sys.maxsize, ...

(emphasis mine). New style classes don't implement __getslice__() by default, so

If no __getslice__() is found, a slice object is created instead, and passed to __getitem__() instead.

Python 3 doesn't support __getslice__(), anymore, instead it constructs a slice() object for all of the above slice expressions. And slice() has None as default:

Note: Slicing is done exclusively with the following three methods. A call like

a[1:2] = b

is translated to

a[slice(1, 2, None)] = b

and so forth. Missing slice items are always filled in with None.

Upvotes: 10

Related Questions