使用 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 时我听说过一件事,它会截断大序列。所以,这是一个潜在的失败,但似乎原生 list
和 set
类型不会那样做。
其他注意事项:
- 我无法使用 ,因为我将要使用嵌套词典。
- 我在测试时使用了 python 3.9.7。
- 无法使用 ,因为在散列时它仍然有 IPv4 地址对象作为键。 (json.dumps 不太喜欢)
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? 的建议...为什么要偏离它?
所以,我看到了 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 时我听说过一件事,它会截断大序列。所以,这是一个潜在的失败,但似乎原生 list
和 set
类型不会那样做。
其他注意事项:
- 我无法使用 ,因为我将要使用嵌套词典。
- 我在测试时使用了 python 3.9.7。
- 无法使用 ,因为在散列时它仍然有 IPv4 地址对象作为键。 (json.dumps 不太喜欢)
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? 的建议...为什么要偏离它?