On Fri, Aug 20, 2010 at 12:55 PM, Gregory, Matthew
<[email protected]> 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 - [email protected]
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor