point class help

R

r

I am hacking up a point class but having problems with how to properly
overload some methods. in the __add__, __sub__, __iadd__, __isub__, I
want to have the option of passing an instance or a container(list,
tuple) like
Point2d(30,30)


here is what i have, it would seem stupid to use a conditional in each
method like this...

def method(self, other):
if isinstance(other, Point2d):
x, y = origin.x, origin.y
else:
x, y = origin[0], origin[1]
#modify self.x & self.y with x&y

there must be a way to get the x, y with reusable code, i am not about
to have this conditional under every method call, What am i missing
here?


class Point2d():
def __init__(self, x, y=None):
if type(x) == tuple:
self.x = x[0]
self.y = x[1]
else:
self.x = x
self.y = y

def __str__(self):
return 'Point2d(%f, %f)' %(self.x, self.y)

def __add__(self, other):
if isinstance(other, Point2d):
x, y = origin.x, origin.y
else:
x, y = origin[0], origin[1]
return (self.x+x, self.y+y)

def __sub__(self, other):
pass

def __iadd__(self, other): #+=
pass

def __isub__(self, other): #-=
pass

any ideas?
 
R

r

before anybody say's anything, i screwed up when i pasted the code,
here is what i really have...

def method(self, other):
if isinstance(other, Point2d):
x, y = other.x, other.y
else:
x, y = other[0], other[1]
return self.x+x, self.y+y


#and the fixed class :)
class Point2d():
def __init__(self, x, y=None):
if type(x) == tuple:
self.x = x[0]
self.y = x[1]
else:
self.x = x
self.y = y
def __str__(self):
return 'Point2d(%f, %f)' %(self.x, self.y)
def __add__(self, other):
if isinstance(other, Point2d):
x, y = other.x, other.y
else:
x, y = other[0], other[1]
return (self.x+x, self.y+y)
def __sub__(self, other):
pass
def __iadd__(self, other): #+=
pass
def __isub__(self, other): #-=
pass

PS: i know i could have one method like

def get_xy(self, other):
#conditional

and then call it like

x, y = self.get_xy(other)

but that seems pretty clumsy. There must be a more Pythonic way!
 
S

Steve Holden

r said:
I am hacking up a point class but having problems with how to properly
overload some methods. in the __add__, __sub__, __iadd__, __isub__, I
want to have the option of passing an instance or a container(list,
tuple) like
Point2d(30,30)


here is what i have, it would seem stupid to use a conditional in each
method like this...

def method(self, other):
if isinstance(other, Point2d):
x, y = origin.x, origin.y
else:
x, y = origin[0], origin[1]
#modify self.x & self.y with x&y

there must be a way to get the x, y with reusable code, i am not about
to have this conditional under every method call, What am i missing
here?
Not much. If you want these points to be freely mixable with containers
then you should define a function like makePoint:

def makePoint(x):
if type(x) is Point: # assumes new-style classes
return x
else:
return Point(x)
class Point2d():
def __init__(self, x, y=None):
if type(x) == tuple:
self.x = x[0]
self.y = x[1]
else:
self.x = x
self.y = y

def __str__(self):
return 'Point2d(%f, %f)' %(self.x, self.y)

def __add__(self, other):
if isinstance(other, Point2d):
x, y = origin.x, origin.y
else:
x, y = origin[0], origin[1]
return (self.x+x, self.y+y)

def __sub__(self, other):
pass

def __iadd__(self, other): #+=
pass

def __isub__(self, other): #-=
pass

any ideas?

Then your __add__ method would become:

def __add__(self, other):
other = makePoint(other)
return (self.x+other.x, self.y+other.y)

Thous it does seem particularly perverse to have the add method not
itself return a Point.

regards
Steve
 
R

r

Thous it does seem particularly perverse to have the add method not
itself return a Point.

Thanks Steve,
i was going implement exactly this but thought there "might" be a
better way i did not know about. So i feel better about myself
already. And your right, i should be returning a Point2d()
Many Thanks
 
M

Matimus

Thanks Steve,
i was going implement exactly this but thought there "might" be a
better way i did not know about. So i feel better about myself
already. And your right, i should be returning a Point2d()
Many Thanks

I just inherited from tuple and did it like this. Note that this
served my needs, but it definitely needs some work to become general
purpose. Also note that I used '__new__' instead of __init__, making
this type immutable.

class Point(tuple):
"Simple immutable point class (vector) supports addition and
subtraction"

def __new__(cls, x, y=None):
if y is None:
x, y = x
return super(Point, cls).__new__(cls,(x, y))

def __add__(self, p):
return Point(self[0]+p[0], self[1]+p[1])

def __sub__(self, p):
return Point(self[0]-p[0], self[1]-p[1])

def __neg__(self):
return Point(-self[0], -self[1])

def __pos__(self):
return self

def __str__(self):
return "Point(%d, %d)"%(self[0], self[1])

__repr__ = __str__



Matt
 
S

Sion Arrowsmith

r said:
here is what i have, it would seem stupid to use a conditional in each
method like this...

def method(self, other):
if isinstance(other, Point2d):
x, y = origin.x, origin.y
else:
x, y = origin[0], origin[1]
#modify self.x & self.y with x&y

Here's another alternative (I'd've gone with the subclassing tuple if
writing this from scratch):

class Point2d(object):
...
def __getitem__(self, i):
if not 0 <= i <= 1:
raise IndexError
return getattr(self, ['x', 'y'])

def method(self, other):
x, y = other[0], other[1]
...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top