类自定义__eq__作为哈希的比较

问题描述 投票:2回答:1

考虑一个自定义类:

class MyObject:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __hash__(self):
        return hash((self.a, self.b))

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__hash__() == other.__hash__()

使等式依赖于哈希是一个坏主意吗?这似乎是一种更优雅和可读的机制,而不是以零散的方式检查每对属性以获得更多的属性ala

self.a == other.a and self.b == other.b and ... self.n == other.n

或使用getattr和列表进行更动态的检查(有更好的方法来比较大量的属性对吗?)

内置散列函数返回的散列的大小是否不足以在相对较大的数据集中可靠?

python class hash equality
1个回答
3
投票

是的,这是一个坏主意。散列不是唯一的,具有相等散列的对象也不能保证实际上相等:

>>> (-1, 0) == (-2, 0)
False
>>> hash((-1, 0)) == hash((-2, 0))
True

哈希并不是唯一的;它们是一种快速选择有限大小的hash table中的插槽的方法,以便于O(1)字典查找,并允许和预期碰撞。

是的,Python要求相等的对象应该具有相等的哈希值,但这并不意味着可以颠倒关系。

我只是比较元组:

def __eq__(self, other):
    return (self.a, self.b) == (other.a, other.b)

如果您正在编写大量数据类,那么所有需要相等测试和散列等的简单类都使用dataclasses module(Python 3.7或更高版本,或者使用backport):

from dataclasses import dataclass

@dataclass(frozen=True)
class MyObject:
    a: int
    b: int

上面的类现在有一个__hash____equals__方法:

>>> MyObject(-1, 0) == MyObject(-2, 0)
False
>>> hash(MyObject(-1, 0)) == hash(MyObject(-2, 0))
True
>>> MyObject(42, 12345) == MyObject(42, 12345)
True
© www.soinside.com 2019 - 2024. All rights reserved.