Rodhri, thank you very much for your reply. I've tried to extend what you suggested; I think it can be made to work, but you're right -- it gets horrid rapidly. I'm at the start of what promises to be a large project, and I want to make sure that I get my data structures right, but my impression right now is that the memory efficiency of views is negated by the computational complexity of their implementation. So I think I will stick to copies and be done with it.
For the record, part of the reason I wanted a view was that my class will be inherited from numpy.ndarray, where, by default, slices return views. Thanks again, -AM On 22 May, 00:20, "Rhodri James" <rho...@wildebst.demon.co.uk> wrote: > On Thu, 21 May 2009 13:08:39 +0100, <youh...@googlemail.com> wrote: > > Hi, > > > I'm trying to create a new class of list that has periodic boundary > > conditions. > > > Here's what I have so far: > > > class wrappedList(list): > > def __getitem__(self, p): > > return list.__getitem__(self, p%len(self)) > > def __setitem__(self, p, v): > > list.__setitem__(self, p%len(self), v) > > >>>>> a=wrappedList(range(10)) > >>>>> a[1] > > 1 > >>>>> a[11] > > 1 > > > But I would also like to make slices. For instance I would like > >>>>> a[8:11] > > [8, 9, 0] > > > I can do it by copying, but I want to return a view to the original > > data, and I have no idea where to start. It seems that the slice needs > > to retain some knowledge of the list from which it derived. i.e. it > > needs to know that it is a slice. Any ideas on how I can extend this > > to allow views? > > Reading the docs, this looks like a very messy area of Python 2.x in > that for a builtin like `list` you have to provide a __getslice__ method > despite it being deprecated and only dealing with simple slices. Good > luck with that. In Python 3, you just have to deal with the fact that > your __getitem__ and __setitem__ `p` arguments can be slice objects > instead of integers. > > If you're set on making your slices views on the original (which means > that changes to the slice will change the original, unlike normal lists!) > then you need to extend your class to remember what it's viewing, and > what the start, stop and step of the slice were. When it's a view, it > passes (massaged) requests up to its parent. There's a cute (but likely > inefficient) way of doing this that uses the fact that your view is still > a list under the hood, and stashes the parental indices in it. This will > also make len() work correctly, for a bonus :-) It gets quite horrid > quite fast, but here's a very incomplete untested skeleton: > > class wrappedList(list): > def __init__(self, parent=None, *args): > list.__init__(self, *args) > self.parent = parent > > def __getitem__(self, p): > if self.parent is None: > self.primary_getitem(p) > else: > self.view_getitem(p) > > def view_getitem(self, p): > return self.parent[list.__getitem__(self, p%len(self))] > > ...and similarly for __setitem__, where primary_getitem() is your > previous __getitem__ method. All four need to be modified to cope > with slices, of course, and to create new wrappedList objects. > Something like this: > > if isinstance(p, slice): > if p.start is None: > start = 0 > else: > start = p.start > if p.step is None: > step = 1 > else: > step = p.step > indices = range(start, p.stop, step) > return wrappedList(indices, parent=self) > > This will go horribly, horribly wrong if you delete anything from > your original list, but I can't off-hand think of a view method > that won't. > > -- > Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list