[Tutor] design of Point class

Wayne Werner waynejwerner at gmail.com
Fri Aug 20 18:14:38 CEST 2010


On Fri, Aug 20, 2010 at 10:45 AM, Gregory, Matthew <
matt.gregory at oregonstate.edu> wrote:

> Hi all,
>
> I often struggle with object design and inheritance.  I'd like opinions on
> how best to design a Point class to be used in multiple circumstances.
>
> I typically deal with geographic (either 2D or 3D) data, yet there are
> occasions when I need n-dimensional points as well.  My thought was to
> create a superclass which was an n-dimensional point and then subclass that
> to 2- and 3-dimensional cases.  The rub to this is that in the n-dimensional
> case, it probably makes most sense to store the actual coordinates as a list
> whereas with the 2- and 3-D cases, I would want 'named' variables, such as
> x, y, z.
>
> Here's a (very rough) first cut at the constructor and a generic distance
> function for the n-dimensional case:
>
> class PointND(object):
>    def __init__(self, a_list):
>        self.a_list = a_list[:]
>
>    def distance(self, right):
>        assert(len(self.coord) == len(right))
>        squared_diffs = [(i-j)*(i-j) for (i,j) in zip(self.coord, right)]
>        return math.sqrt(sum(squared_diffs))
>
> But how can I subclass this in such a way to be able to:
>
> 1) Have named variables in the 2- and 3-D cases
> 2) Be able to initialize with separate passed values, e.g. 'p =
> Point2D(3.0, 5.0)'
>   rather than passing in a list
>

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

HTH,
Wayne
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20100820/592e6ba9/attachment.html>


More information about the Tutor mailing list