On Fri, Aug 20, 2010 at 12:55 PM, Gregory, Matthew <matt.greg...@oregonstate.edu> wrote: > Wayne Werner wrote: >> class Point2D(PointND): >> def __init__(self, x = 0, y = 0): >> super(Point2D, self).__init__([x,y]) >> self.x = 0 >> self.y = 0 >> >> though you wouldn't be able to directly modify the values, or you'll >> lose the distance function. You'd have to create setter functions, and as >> such should rename x and y to _x and _y, to indicate that sure you *can* >> touch >> these, but really you shouldn't. >> >> For the 3d, you'd just add a z param, although to really generalize your >> ND class you could do this instead: >> >> class PointND(object): >> def __init__(self, x=0, y=0, z=0, a_list=None): >> if a_list is not None: >> self.a_list = a_list[:] >> self.x = x >> self.y = y >> self.z = z >> >> def coords(self): >> return [self.x, self.y, self.z] + self.a_list >> ... >> >> Then your subclass takes less effort: >> >> class Point2D(PointND): >> def __init__(self, x=0, y=0): >> super(Point2D, self).__init__(x,y) >> >> and this allows you to access point.x, point.y, and point.z directly. >> >> Of course you could also subclass list with ND and just use descriptors >> for self[0], self[1], and self[2]: >> http://users.rcn.com/python/download/Descriptor.htm > > Thanks all for good suggestions. I'm intrigued by the idea of subclassing > list (suggested by both Bob and Wayne) and using x, y and z as descriptors to > the elements in the list. Obviously, it's important that the descriptors > (x,y,z) stay in sync with the list itself so that: > > >>> p = PointND(1,2,3) > >>> p.x = 10 > >>> p > [10,2,3] > > >From what I understood of the link Wayne sent, I should be able to use > >__set__ to create this relationship between the labels and the list, but I'm > >totally lost on how to do this. It seems like x,y,z need to be instances of > >descriptor objects who have values that are associated with the list. > > In the mean time, I've overridden __setattr__ to enforce this, but it looks a > bit crufty. Any further suggestions are most welcome. > > class PointND(list): > def __init__(self, *a_list): > super(PointND, self).__init__(a_list) > if len(self) <= 3: > self.x = self[0] > if len(self) >= 2 and len(self) <= 3: > self.y = self[1] > if len(self) == 3: > self.z = self[2] > > def __setattr__(self, attr, value): > if attr in ('x', 'y', 'z'): > self.__dict__[attr] = value > if attr == 'x': > self[0] = value > elif attr == 'y': > self[1] = value > else: > self[2] = value
perhaps properties could be of some use? from operator import itemgetter, setitem def named_index(index): getter = itemgetter(index) setter = lambda self, val: setitem(self, index, val) return property(getter, setter) class NPoint(list): x = named_index(0) y = named_index(1) z = named_index(2) p = NPoint([3, 4, 50]) print p.x, p.y, p.z p.x = p.y + 13 print p Note that trying to access z when there are not enough items in the list will raise an IndexError, not an AttributeError. You might want to adjust the getter/setter functions a little. Alternatively, I'm not sure if you can add properties in __init__ or __new__, but if not that, you can probably write a metaclass that adds in the right properties based on list length. Hugo _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor