我有一个代码可以为我计算欧几里得距离:
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 distance(self, other):
new_x = self._x - other._x
new_y = self._y - other._y
print(new_x,' ',new_y)
return (new_x ** 2 + new_y ** 2) ** 0.5
p1 = Point(10, 4)
p2 = Point(3, 1)
print('Euclidean distance : 'p1.distance(p2))
但是,现在我要使用__sub__
和__pow__
之类的python中的魔术方法来计算此距离。我已经成功实现了__sub__
,但是我不知道如何为__pow__
和平方根实现。到目前为止,这是我的代码:
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)
p1 = Point_1(10,4)
print(p1.getX())
p2 = Point_1(3,1)
print(p2.getX())
p3 = p1 - p2
如何使用魔术方法来实现公式的其余部分。我真的很困惑帮助我将不胜感激。
答案 0 :(得分:2)
如上所述,使用Point类表示向量可能不是一个好主意。在简单的程序中没关系,但是在更复杂的代码中可能会造成混淆。通常的做法是使积分不变。但是无论如何...
要执行此欧几里德距离运算,我们可以“滥用”新的__matmul__
魔术方法。此方法由@
运算符调用。这是一个基于您的代码的简短演示。请注意,我使用x
和y
作为属性,没有充分的理由将它们标记为私有。
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)
输出
Point(7, 8)
Point(3, 4)
5.0
答案 1 :(得分:1)
将两个点的差作为一个点是没有意义的。看来您要实现的对象实际上是一个向量。
然后,该距离对应于用__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
答案 2 :(得分:0)
请注意,您对__pow__
的定义对于矢量来说有点不规范。
但实际上,两个点p1
和p2
的距离可以写为sum((p1 - p2)**2)**.5
。因此,我们需要您的__pow__
方法,您的__sub__
方法,以及唯一可以添加的__iter__
方法,该方法允许sum
起作用:
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
这是基于现有代码的最短方法。您可以通过添加标量乘法方法和加法方法,然后将sub定义为p1 + (-1)*p2
来进行进一步的实验。您还可以通过实现__repr__
方法来简化自己的工作。
答案 3 :(得分:0)
您的二等班为我工作。我看不到任何问题:
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)
然后:
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)
称其为向量或点或其他任何东西,似乎在执行您想要的操作。