使用 python 个对象在字典中进行更一致的散列?

More consistent hashing in dictionary with python objects?

所以,我看到了 Hashing a dictionary?,我正试图找到一种方法来更好地处理 python 本机对象并产生稳定的结果。

在查看了所有答案和评论之后,这就是我得出的结论,一切似乎都正常,但我是否可能遗漏了一些会使我的散列不一致的东西(除了散列算法冲突)?

md5(repr(nested_dict).encode()).hexdigest()

tl;dr:它使用 repr 创建一个字符串,然后对该字符串进行哈希处理。

用这个生成了我的测试嵌套字典:

for i in range(100):
    for j in range(100):
        if not nested_dict.get(i,None):
            nested_dict[i] = {}
        nested_dict[i][j] = ''

我想 repr 应该能够支持任何 python 对象,因为大多数对象通常都必须有 __repr__ 支持,但我对 [=42 还是很陌生=] 编程。在使用 from reprlib import repr 而不是 stdlib 时我听说过一件事,它会截断大序列。所以,这是一个潜在的失败,但似乎原生 listset 类型不会那样做。

其他注意事项:

Python 字典是插入顺序的。代表尊重这一点。 {"A":1,"B":2} 的 hexdigest 将不同于 {"B":2,"A":1}== - 明智的是那些字典是相同的。

你的不行:

from  hashlib import md5

def yourHash(d):
    return md5(repr(d).encode()).hexdigest()

a = {"A":1,"B":2}
b = {"B":2,"A":1}

print(repr(a)) 
print(repr(b))
print (a==b)

print(yourHash(a) == yourHash(b))

给予

{'A': 1, 'B': 2}   # repr a
{'B': 2, 'A': 1}   # repr b
True               # a == b

False              # your hashes equall'ed

我真的完全看不到散列字典的“意义”……而且这里的那些甚至都没有“嵌套”。


您可以尝试 JSON 将键排序到最后一个嵌套的键,并使用要散列的整个结构的 json.dumps() - 但仍然 - 看不到意义,它会给你大量的计算开销:

import json
a = {"A":1,"B":2, "C":{2:1,3:2}}
b = {"B":2,"A":1, "C":{3:2,2:1}}

for di in (a,b):
    print(json.dumps(di,sort_keys=True))

给予

{"A": 1, "B": 2, "C": {"2": 1, "3": 2}}  # thouroughly sorted
{"A": 1, "B": 2, "C": {"2": 1, "3": 2}}  # recursively...

这正是 this answer in Hashing a dictionary? 的建议...为什么要偏离它?