It's actually not too difficult to implement this yourself using range
.* You can slice a range and it does all of the complicated arithmetic for you:
>>> range(20)[10:]
range(10, 20)
>>> range(10, 20)[::2]
range(10, 20, 2)
>>> range(10, 20, 2)[::-3]
range(18, 8, -6)
So you just need a class of object that contains a reference to the original sequence, and a range. Here is the code for such a class (not too big, I hope):
class SequenceView:
def __init__(self, sequence, range_object=None):
if range_object is None:
range_object = range(len(sequence))
self.range = range_object
self.sequence = sequence
def __getitem__(self, key):
if type(key) == slice:
return SequenceView(self.sequence, self.range[key])
else:
return self.sequence[self.range[key]]
def __setitem__(self, key, value):
self.sequence[self.range[key]] = value
def __len__(self):
return len(self.range)
def __iter__(self):
for i in self.range:
yield self.sequence[i]
def __repr__(self):
return f"SequenceView({self.sequence!r}, {self.range!r})"
def __str__(self):
if type(self.sequence) == str:
return ''.join(self)
elif type(self.sequence) in (list, tuple):
return str(type(self.sequence)(self))
else:
return repr(self)
(This was bodged together in about 5 minutes, so make sure you test it thoroughly before using it anywhere important.)
Usage:
>>> p = list(range(10))
>>> q = SequenceView(p)[3:6]
>>> print(q)
[3, 4, 5]
>>> q[1] = -1
>>> print(q)
[3, -1, 5]
>>> print(p)
[0, 1, 2, 3, -1, 5, 6, 7, 8, 9]
* in Python 3