I have a code that calculates Euclidean distance for me:
class Point:
\"\"\"A point in two-dimensional space.\"\"\"
def __init__(self, x, y):
se
As has been mentioned, it may not be a good idea to use a Point class to represent vectors. It's ok in simple programs, but it can get confusing in more complex code. The usual practice is to make points immutable. But anyway...
To do this Euclidean distance operation we can "abuse" the new __matmul__ magic method. This method is invoked by the @
operator. Here's a short demo based on your code. Notice that I'm using x
and y
as the attributes, there's no good reason to mark them as private.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point({}, {})".format(self.x, self.y)
def __add__ (self, other ):
return Point(self.x + other.x, self.y + other.y)
def __sub__ (self, other ):
return Point(self.x - other.x, self.y - other.y)
def __pow__(self, p):
return Point(self.x ** p, self.y **p)
def __abs__(self):
d = self ** 2
return (d.x + d.y) ** 0.5
def __matmul__(self, other):
''' Euclidean distance between self & other '''
return abs(self - other)
# Test
a = Point(5, 6)
b = Point(2, 2)
print(a + b)
print(a - b)
print(a @ b)
output
Point(7, 8)
Point(3, 4)
5.0
It does not make sense for the difference of two points to be a point. It seems the object you are trying to implement is in fact a vector.
Then the distance corresponds to the norm of a vector, implemented with __abs__
.
class Vector:
def __init__(self, *args):
self._coords = args
def __add__(self, other):
return Vector(*[x + y for x, y in zip(self._coords, other._coords)])
def __sub__(self, other):
return Vector(*[x - y for x, y in zip(self._coords, other._coords)])
def __abs__(self):
"""Euclidian norm of the vector"""
return sum(x**2 for x in self._coords) ** (1 / 2)
v1 = Vector(1, 3)
v2 = Vector(4, -1)
print(abs(v2 - v1)) # 5.0
# Also works in higher dimensions
v3 = Vector(1, -1, 0)
v4 = Vector(4, 6, -2)
print(abs(v3 - v4)) # 7.87
Note that your definition of __pow__
is a bit nonstandard for vectors.
But as it is, the distance of two points p1
and p2
could be written as sum((p1 - p2)**2)**.5
. So we need your __pow__
method, your __sub__
method, and the only other addition is an __iter__
method which allows sum
to work:
class Point:
"""A point in two-dimensional space."""
def __init__(self, x, y):
self._x = x
self._y = y
def __eq__(self, other):
return self._x == other._x and self._y == other._y
def __sub__(self, other):
return Point(self._x - other._x, self._y - other._y)
def __pow__(self, power):
return Point(self._x**power, self._y**power)
def __iter__(self):
yield self._x
yield self._y
def distance(self, other):
return sum((self - other)**2)**.5
p1 = Point(2, 3)
p2 = Point(5, -1)
print(p1.distance(p2))
Out: 5.0
That's the shortest way based on your existing code anyway. You could experiment further by adding a scalar multiplication method and an addition method and then defining sub as p1 + (-1)*p2
. You can also make things a bit easier on yourself by implementing a __repr__
method.
Your second class works for me. I do not see any issues with it:
In [9]: class Point_1(object):
...:
...: def __init__(self, x, y):
...: self._x = x
...: self._y = y
...:
...:
...: def setX(self, x,y):
...: self._x = x
...: self._y = y
...:
...: def getX(self):
...: return self._x,self._y
...:
...:
...: def __sub__ (self, other ):
...: return Point_1(self._x - other._x, self._y - other._y)
...:
...: def __pow__(self,p):
...: return Point_1(self._x ** p, self._y **p)
And then:
In [14]: p1 = Point_1(10,4)
...: print(p1.getX())
...:
...: p2 = Point_1(3,1)
...: print(p2.getX())
...:
...: p3 = p1 - p2
...:
...:
(10, 4)
(3, 1)
In [15]: p3.getX()
Out[15]: (7, 3)
Call it vector or point or whatever, it seems to be doing what you want it to do.