The Python Documentation states that
slice indices are silently truncated to fall in the allowed range
and therefor no IndexErrors are risen when slicing a list, regardless what start or stop parameters are used:
>>> egg = [1, "foo", list()]
>>> egg[5:10]
[]Since the list egg does not contain any indices greater then 2, a egg[5] or egg[10] call would raise an IndexError:
>> egg[5]
Traceback (most recent call last):
IndexError: list index out of rangeThe question is now, how can we raise an IndexError, when both given slice indices are out of range?
2 Answers
In Python 2 you can override __getslice__ method by this way:
class MyList(list): def __getslice__(self, i, j): len_ = len(self) if i > len_ or j > len_: raise IndexError('list index out of range') return super(MyList, self).__getslice__(i, j)Then use your class instead of list:
>>> egg = [1, "foo", list()]
>>> egg = MyList(egg)
>>> egg[5:10]
Traceback (most recent call last):
IndexError: list index out of range There is no silver bullet here; you'll have to test both boundaries:
def slice_out_of_bounds(sequence, start=None, end=None, step=1): length = len(sequence) if start is None: start = 0 if step > 1 else length if start < 0: start = length - start if end is None: end = length if step > 1 else 0 if end < 0: end = length - end if not (0 <= start < length and 0 <= end <= length): raise IndexError()Since the end value in slicing is exclusive, it is allowed to range up to length.