A list with periodic boundary conditions

youhvee at googlemail.com youhvee at googlemail.com
Tue May 26 05:45:40 EDT 2009


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... at wildebst.demon.co.uk> wrote:
> On Thu, 21 May 2009 13:08:39 +0100, <youh... at 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




More information about the Python-list mailing list