[Tutor] design of Point class

Gregory, Matthew matt.gregory at oregonstate.edu
Fri Aug 20 19:55:02 CEST 2010


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 


More information about the Tutor mailing list