为了缓存目的,我需要从字典中存在的GET参数生成一个缓存键。
目前,我正在使用sha1(repr(sorted(my_dict.items()))) (sha1()是一个内部使用hashlib的方便方法),但我很好奇是否有更好的方法。
为了缓存目的,我需要从字典中存在的GET参数生成一个缓存键。
目前,我正在使用sha1(repr(sorted(my_dict.items()))) (sha1()是一个内部使用hashlib的方便方法),但我很好奇是否有更好的方法。
当前回答
更新自2013年回复…
以上答案在我看来都不可靠。原因是使用了items()。据我所知,这是一个依赖于机器的顺序。
这个怎么样?
import hashlib
def dict_hash(the_dict, *ignore):
if ignore: # Sometimes you don't care about some items
interesting = the_dict.copy()
for item in ignore:
if item in interesting:
interesting.pop(item)
the_dict = interesting
result = hashlib.sha1(
'%s' % sorted(the_dict.items())
).hexdigest()
return result
其他回答
更新自2013年回复…
以上答案在我看来都不可靠。原因是使用了items()。据我所知,这是一个依赖于机器的顺序。
这个怎么样?
import hashlib
def dict_hash(the_dict, *ignore):
if ignore: # Sometimes you don't care about some items
interesting = the_dict.copy()
for item in ignore:
if item in interesting:
interesting.pop(item)
the_dict = interesting
result = hashlib.sha1(
'%s' % sorted(the_dict.items())
).hexdigest()
return result
这不是一个通用的解决方案(即,如果你的字典不是嵌套的,它只是微不足道的工作),但由于这里没有人建议它,我认为分享它可能是有用的。
我们可以使用(第三方)不可变包创建一个字典的不可变“快照”,如下所示:
from immutables import Map
map = dict(a=1, b=2)
immap = Map(map)
hash(immap)
这似乎比原始字典的字符串化要快。
我是从一篇不错的文章中学到的。
使用sorted(d.s items())并不足以获得稳定的repr。d中的一些值也可以是字典,它们的键仍然会以任意顺序出现。只要所有的键都是字符串,我更喜欢使用:
json.dumps(d, sort_keys=True)
也就是说,如果散列需要在不同的机器或Python版本之间保持稳定,我不确定这是万无一失的。您可能希望添加分隔符和ensure_ascii参数,以保护自己不受对默认值的任何更改的影响。我很感激你的评论。
您可以使用地图库来做到这一点。具体来说,地图。FrozenMap
import maps
fm = maps.FrozenMap(my_dict)
hash(fm)
要安装地图,只需执行:
pip install maps
它也处理嵌套的dict大小写:
import maps
fm = maps.FrozenMap.recurse(my_dict)
hash(fm)
免责声明:我是地图库的作者。
这里有一个更清晰的解决方案。
def freeze(o):
if isinstance(o,dict):
return frozenset({ k:freeze(v) for k,v in o.items()}.items())
if isinstance(o,list):
return tuple([freeze(v) for v in o])
return o
def make_hash(o):
"""
makes a hash out of anything that contains only list,dict and hashable types including string and numeric types
"""
return hash(freeze(o))