I have a large list l
. I want to create a view from element 4 to 6. I can do it with sequence slice.
>>> l = range(10) >>> lv = l[3:6] >>> lv [3, 4, 5]
However lv
is a copy of a slice of l
. If I change the underlying list, lv
does not reflect the change.
>>> l[4] = -1 >>> lv [3, 4, 5]
Vice versa I want modification on lv
reflect in l
as well. Other than that the list size are not going to be changed.
I’m not looking forward to build a big class to do this. I’m just hoping other Python gurus may know some hidden language trick. Ideally I hope it can be like pointer arithmetic in C:
int lv[] = l + 3;
Answer
There is no “list slice” class in the Python standard library (nor is one built-in). So, you do need a class, though it need not be big — especially if you’re content with a “readonly” and “compact” slice. E.g.:
import collections class ROListSlice(collections.Sequence): def __init__(self, alist, start, alen): self.alist = alist self.start = start self.alen = alen def __len__(self): return self.alen def adj(self, i): if i<0: i += self.alen return i + self.start def __getitem__(self, i): return self.alist[self.adj(i)]
This has some limitations (doesn’t support “slicing a slice”) but for most purposes might be OK.
To make this sequence r/w you need to add __setitem__
, __delitem__
, and insert
:
class ListSlice(ROListSlice): def __setitem__(self, i, v): self.alist[self.adj(i)] = v def __delitem__(self, i, v): del self.alist[self.adj(i)] self.alen -= 1 def insert(self, i, v): self.alist.insert(self.adj(i), v) self.alen += 1