为了缓存目的,我需要从一个包含在字典中的GET参数生成一个缓存键。
目前,我正在使用sha1(repr(sorted(my_dict.items())))
(sha1()
是一个使用hashlib内部的便捷方法),但我很好��是否有更好的方法。
为了缓存目的,我需要从一个包含在字典中的GET参数生成一个缓存键。
目前,我正在使用sha1(repr(sorted(my_dict.items())))
(sha1()
是一个使用hashlib内部的便捷方法),但我很好��是否有更好的方法。
frozendict
模块 来冻结你的字典并使其可哈希化。from frozendict import frozendict
my_dict = frozendict(my_dict)
处理嵌套对象,您可以选择:
import collections.abc
def make_hashable(x):
if isinstance(x, collections.abc.Hashable):
return x
elif isinstance(x, collections.abc.Sequence):
return tuple(make_hashable(xi) for xi in x)
elif isinstance(x, collections.abc.Set):
return frozenset(make_hashable(xi) for xi in x)
elif isinstance(x, collections.abc.Mapping):
return frozendict({k: make_hashable(v) for k, v in x.items()})
else:
raise TypeError("Don't know how to make {} objects hashable".format(type(x).__name__))
functools.singledispatch
(Python 3.7):@functools.singledispatch
def make_hashable(x):
raise TypeError("Don't know how to make {} objects hashable".format(type(x).__name__))
@make_hashable.register
def _(x: collections.abc.Hashable):
return x
@make_hashable.register
def _(x: collections.abc.Sequence):
return tuple(make_hashable(xi) for xi in x)
@make_hashable.register
def _(x: collections.abc.Set):
return frozenset(make_hashable(xi) for xi in x)
@make_hashable.register
def _(x: collections.abc.Mapping):
return frozendict({k: make_hashable(v) for k, v in x.items()})
# add your own types here
DataFrame
是Hashable
的一个实例,因为它具有__hash__
函数,即使该函数返回错误消息。 - James Hirschorn<frozendict {'a': 2, 'b': 1}>
每次运行 Python 脚本时返回不同的哈希值。 - James Hirschornimport maps
fm = maps.FrozenMap(my_dict)
hash(fm)
maps
只需执行以下操作:pip install maps
dict
情况:import maps
fm = maps.FrozenMap.recurse(my_dict)
hash(fm)
maps
库的作者。.recurse
处理嵌套结构。请参见https://maps.readthedocs.io/en/latest/api.html#maps.FrozenMap.recurse。列表中的排序在语义上是有意义的,如果您想要无序性,则可以在调用`.recurse`之前将列表转换为集合。您还可以利用`.recurse`的`list_fn`参数来使用不同于`tuple`(例如`frozenset`)的可哈希数据结构。 - Pedro Cattorihash(tuple(my_dict.items()))
对于嵌套结构,在顶层字典中具有字符串键时,您可以使用pickle(protocol = 5)并对字节对象进行哈希处理。如果需要安全性,可以使用安全序列化器。
这不是一个通用的解决方案(即仅在您的字典未嵌套时才能轻松工作),但由于没有人建议过,我认为分享它可能会有用。
可以使用(第三方)immutables包,并像这样创建一个不可变的字典“快照”:
from immutables import Map
map = dict(a=1, b=2)
immap = Map(map)
hash(immap)
这似乎比原始字典的字符串化更快。
我从这篇不错的文章中了解到了这一点。
def dict_hash(dictionary: Dict[str, Any]) -> str:
"""MD5 hash of a dictionary."""
dhash = hashlib.md5()
##sortedString = yaml.dump(dictionary, sort_keys=True)
sortedString = str(collections.OrderedDict({k:dictionary[k] for k in sorted(dictionary)}))
encoded = sortedString.encode()
dhash.update(encoded)
return dhash.hexdigest()
hash(str(my_dict))
hash(str({'a': 1, 'b': 2})) != hash(str({'b': 2, 'a': 1}))
(尽管对于某些字典可能有效,但不能保证适用于所有字典)。 - Vlad Frolov
在语义上与
{'b':2, 'a':1}`相同)。我还没有在任何太复杂的东西上使用过它,所以效果可能有所不同,但欢迎反馈。 - Oliverrepr()
函数(在 Python 3 中可能还需要加上.encode()
)。 - ThiefMaster