类的两个实例相等,但哈希代码不同

2024-05-15 08:25:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一个空间几何项目,我有不同的几何实体,其中包括点。有时两点是相等的,但由于计算的原因,数值误差很小,比如1和1.0000000001,所以我用math.isclose()函数实现了__eq__方法来解决这个问题

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__方法以使这两个对象相等

最终目标是使用以下函数“uniquify”此类对象的列表并删除重复项:

def f12(seq):
    # from Raymond Hettinger
    # https://twitter.com/raymondh/status/944125570534621185
    return list(dict.fromkeys(seq))

Tags: 方法函数selfreturnifdefmathabs
2条回答

你的方法有一个普遍的问题

大多数人都会以相同的方式期待及物性。这意味着当两个点ab相等并且a也等于另一个点c时,那么ac也应该相等。在您的实现中不一定是这样

想象一下,每个点周围都有一个球体,每个点被认为是相等的。下图显示了该球体(或球体半径的一半以上),因此重叠意味着点相等:

point visualization

所以ab应该有相同的散列码bc应该有相同的散列码,但不是ac?这怎么可能呢

我建议添加一个额外的方法is_close_to,并在那里实现逻辑

编辑: @JLPeyret指出,您可以使用网格并计算与包含该点的网格象限对应的点的哈希值。在这种情况下,两个邻近点可能接近网格象限的划分,因此分配了不同的散列值。如果这种概率方法对您有效,请查看locality-sensitive hashing

与其给点一个“无效的”__eq__方法,不如用你已有的代码给点一个isclose方法,用它代替==,或者通过四舍五入坐标使它们在标准意义上相等

相关问题 更多 >