我正在考虑创建一个dict的校验和来知道它是否被修改过
目前我有这个:
>>> import hashlib
>>> import pickle
>>> d = {'k': 'v', 'k2': 'v2'}
>>> z = pickle.dumps(d)
>>> hashlib.md5(z).hexdigest()
'8521955ed8c63c554744058c9888dc30'
也许存在更好的解决方案?
注意:我想创建一个独特的dict id来创建一个好的Etag。
编辑: 我可以在dict中获得抽象数据。
像这样的东西:
reduce(lambda x,y : x^y, [hash(item) for item in d.items()])
获取dict中每个(key,value)元组的哈希值并将它们全部异或。
@katrielalex
如果dict包含不可用的项目,您可以这样做:
hash(str(d))
或者甚至更好
hash(repr(d))
我不知道是否 pickle
保证每次都以相同的方式序列化哈希。
如果你只有字典,我会去打电话的组合 keys()
, sorted()
,根据排序的键/值对构建一个字符串,并计算其上的校验和
如你所说,你想根据字典内容生成一个Etag, OrderedDict 保留字典顺序可能是更好的候选人。只需通过键,值对进行迭代,然后构造您的Etag字符串。
我想你可能没有意识到一些细微之处。第一个问题是项目在dict中出现的顺序不是由实现定义的。这意味着只需要求 str
一个字典不起作用,因为你可以
str(d1) == "{'a':1, 'b':2}"
str(d2) == "{'b':2, 'a':1}"
这些将散列到不同的值。如果你在dict中只有hashable项目,你可以哈希它们然后加入它们的哈希值 @Bart 做或简单
hash(tuple(sorted(hash(x) for x in d.items())))
请注意 sorted
,因为你必须确保散列元组以相同的顺序出现,而不管项目在dict中出现的顺序。如果你在dict中有dicts,你可以解决这个问题,但这会很复杂。
但是如果你允许的话,很容易打破这样的任何实现 随意 字典中的数据,因为你可以简单地写一个破碎的对象 __hash__
实施和使用。你不能使用 id
,因为那时你可能有相同的项目比较不同。
这个故事的寓意是Python中不支持哈希词典。
在Python 3中,哈希函数用随机数初始化,对于每个python会话都是不同的。如果这对于预期的应用是不可接受的,请使用例如zlib.adler32为dict构建校验和:
import zlib
d={'key1':'value1','key2':'value2'}
checksum=0
for item in d.items():
c1 = 1
for t in item:
c1 = zlib.adler32(bytes(repr(t),'utf-8'), c1)
checksum=checksum ^ c1
print(checksum)