Python, __getitem__, slices, and negative indexes

927 views Asked by At

This is an example of Python's behavior with negative numbers passed in slices:

>>> class test:
...     def __getitem__(self, sl):
...          print sl.start, sl.stop, sl.step
...
>>> t = test()
>>> t[0:0:0]
0 0 0
>>> t[-1:0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: test instance has no attribute '__len__'
>>> def __len__(self): return 100
...
>>> test.__len__ = __len__
>>> t[-1:0]
99 0 None
>>>

I want to do my own handling with negative indexes. How can I make Python stop deciding on the slice indexes automagically?

1

There are 1 answers

0
Ferdinand Beyer On

In Python 2.x, you need to use new-style classes by subclassing object, then you get the original parameters of the slice:

>>> class C(object):
...   def __getitem__(self, key):
...     print key
...
>>> c = C()
>>> c[-1:2]
slice(-1, 2, None)

Prior to 2.x, there was a dedicated method for slicing, __getslice__, which is still supported for in Python 2.x and does the interpolation using __len__:

Called to implement evaluation of self[i:j]. The returned object should be of the same type as self. Note that missing i or j in the slice expression are replaced by zero or sys.maxsize, respectively. If negative indexes are used in the slice, the length of the sequence is added to that index. If the instance does not implement the __len__() method, an AttributeError is raised. No guarantee is made that indexes adjusted this way are not still negative. Indexes which are greater than the length of the sequence are not modified. If no __getslice__() is found, a slice object is created instead, and passed to __getitem__() instead.

(emphasis mine)