【发布时间】:2020-06-22 14:34:20
【问题描述】:
我正在研究空间项目中的几何,我有不同的几何实体,其中包括 Point.有时两个点相等,但由于计算导致的小数值误差,例如 1 和 1.0000000001,所以我实现了 __eq__ 方法和 math.isclose() 函数来解决这个问题。
class Point(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __eq__(self, other):
if isinstance(other, Point):
equal_x = math.isclose(other.x, self.x, rel_tol=5e-3, abs_tol=1e-5)
equal_y = math.isclose(other.y, self.y, rel_tol=5e-3, abs_tol=1e-5)
equal_z = math.isclose(other.z, self.z, rel_tol=5e-3, abs_tol=1e-5)
if equal_x and equal_y and equal_z:
return True
return False
在使用集合和字典时,如何实现__hash__ 方法以使这两个对象相等?
最终目标是使用以下函数来“唯一化”此类对象的列表并删除重复项:
def f12(seq):
# from Raymond Hettinger
# https://twitter.com/raymondh/status/944125570534621185
return list(dict.fromkeys(seq))
【问题讨论】:
-
__hash__()的绝对要求是它为__eq__()所说的相等的对象返回相等的值。因此,请考虑您的类中名为X的某个对象,它具有特定的哈希码。向每个坐标添加一点点,以便它们仍然通过isclose()测试:哈希 必须 保持不变。再多加一点,hash 一定还是一样的,以此类推。 唯一__hash__()实现与您的__eq__()一致是返回一个常量 - 这当然会破坏集合或字典的效率。 -
__eq__应该是可传递的,但你的不是。x == y和y == z可能没有x == z为真。 -
Hash 应该是一种快速计算的方法,它为“相同”的事物提供相同的结果(用引号引起来,因为您可以以不同的方式定义它)。最好是“不同”事物的不同结果。 - 最好是这样你甚至可以实现总是返回
1的哈希,但这不会加快速度。 -
在您的情况下,请考虑 xyz 采用什么值 - 并相应地划分空间,例如空间中的 1x1x1 框 10x10x10 => 散列可能是
100*round(x)+10*round(y)+round(z)但正如 chepner 所说,你在这里还有其他问题,我提到的散列的“盒子”将不起作用(1.9(...)95 和 2.0(。 ..)01 在不同的盒子里,但“相等”)
标签: python