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

时间:2019-03-01 12:10:21

标签: python class hash equality

考虑一个自定义类:

import os, time

path = r"c:\users\%myusername%\downloads"
now = time.time()

for filename in os.listdir(path):
    # if os.stat(os.path.join(path, filename)).st_mtime < now - 7 * 86400:
    if os.path.getmtime(os.path.join(path, filename)) < now - 7 * 86400:
        if os.path.isfile(os.path.join(path, filename)):
            print(filename)
            os.remove(os.path.join(path, filename))

让相等依赖于哈希值是一个坏主意吗?这似乎比散乱检查每一对属性来查找更多属性ala更为优雅和易读,

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__()

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

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

1 个答案:

答案 0 :(得分:3)

是的,这是一个坏主意。哈希值不是唯一的,具有相同哈希值的对象也也保证实际上是相等的:

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

散列不是唯一的 ;它们是一种在有限大小的hash table中快速选择插槽的方法,以方便进行O(1)字典查找,并且允许并期望发生冲突。

是的,Python要求相等的对象应具有相等的散列,但这并不意味着关系可以逆转。

我只是比较元组:

from dataclasses import dataclass

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

如果您要编写很多数据类,则所有都需要进行相等性测试和哈希处理等简单类都可以使用dataclasses module(Python 3.7或更高版本,或使用{{ 3}}):

__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 方法:

{{1}}