It is caused by a difference between the slice implementation of Python2 and Python3.
In Python3, obj[x:y]
always equals obj.__getitem__(slice(x,y))
. But in Python2, due to historical reasons, some built-in types(including tuple) implement the slice operator with the __getslice__
method.
__getslice__
uses the __len__
method, __getitem__
does not.
Just run the following code in Python2 and Python3, and you'll see why.
from __future__ import print_function
class MyTuple(tuple):
def __new__(cls, lst, data):
return tuple.__new__(cls, tuple(lst) + (data, ))
def __len__(self):
return tuple.__len__(self) - 1
def __getitem__(self, key):
print("__getitem__() is called. start:%s, end:%s" % (key.start, key.stop))
return super(MyTuple, self).__getitem__(key)
def __getslice__(self, start, end):
print("__getslice__() is called. start:%s, end:%s" % (start,end))
return super(MyTuple, self).__getslice__(start,end)
m = MyTuple([1,2], 0)
print(m[:-1])
According to the Python official doc, you should override __getslice__()
method when you change then __len__
implementation in your subclass.
Reference: