You can use slice
objects, which are passed not to __getslice__
but to __getitem__
when using "extended slicing". Then, move the start
of the slice to 0
, and the stop
to len - 1
while keeping track. Then add zeros:
class MyList(list):
def __getitem__(self, item):
if isinstance(item, slice):
s, e = item.start, item.stop
l = len(self) - 1
left = -s if s < 0 else 0
s = max(s, 0)
right = e - l if e > l else 0
e = min(e, l)
return [0]*left + super(MyList, self).__getitem__(slice(s,e,item.step)) + [0]*right
elif item < 0 or item >= len(self):
return 0
else:
return super(MyList, self).__getitem__(item)
The catch is: you have to force your getslice
call to send a slice
object, which you can do in one of two ways.
>>> a[-2:2:1] # the step = 1 is necessary
[0, 0, 1, 2]
or
>>> a[slice(-2,2)]
[0, 0, 1, 2]
Works on both ends:
>>> a[-2:6:1]
[0, 0, 1, 2, 3, 0, 0, 0]
Original attempt
If __getslice__
was passed the actual arguments given by a[-2:2]
, then this would work:
class MyList(list):
def __getitem__(self, item):
if item < 0 or item >= len(self):
return 0
return super(MyList, self).__getitem__(item)
def __getslice__(self, s, e):
print "input: ", s, e
l = len(self) - 1
left = -s if s < 0 else 0
s = max(s, 0)
right = e - l if e > l else 0
e = min(e, l)
return [0]*left + super(MyList, self).__getslice__(s,e) + [0]*right
But for some reason, a[-2:2]
calls a.__getslice(2,2)
with both values positive.
>>> a[-2:2]
input: 2 2