【问题标题】:A workaround for Python's missing frozen-dict type? [duplicate]Python 缺少 freeze-dict 类型的解决方法? [复制]
【发布时间】:2017-01-19 07:02:57
【问题描述】:

在 Python 中,当您想将列表用作某些字典的键时,可以将它们转换为元组,它们是不可变的,因此是可散列的。

>>> a = {}
>>> a[tuple(list_1)] = some_value
>>> a[tuple(list_2)] = some_other_value

当您想使用 set 对象作为某些字典的键时也会发生同样的情况 - 您可以构建一个 frozenset,它又是不可变的,因此是可散列的。 p>

>>> a = {}
>>> a[frozenset(set_1)] = some_value
>>> a[frozenset(set_2)] = some_other_value

但是对于字典来说似乎没有等价物。

我想到的第一个想法(最后发现它很糟糕)是使用str(some_dict) 作为键。但是,字典总是使用不同的哈希函数(这会影响元素的顺序),所以相等的字典的字符串可能会不同。

是否有任何被称为良好做法的解决方法,或者是否有人有其他想法如何使用类似字典的对象作为其他字典的键?

【问题讨论】:

  • 您可以在collections.OrderedDict 上致电str()
  • @SimeonVisser OrderedDict:除非您将添加元素的顺序视为 dict 值的一部分,否则您可能会对您得到的行为感到惊讶——我曾经认为 OrderedDict 是一个树形图,按键排序,但可惜(对于这个用例)不是。

标签: python dictionary immutability


【解决方案1】:

编辑:

从 Python 3.6 开始,字典保留插入顺序。因此,解决方法会因使用的 Python 版本而异。

对于 Python - 使用 frozenset,这样即使顺序不同,两个集合也是相等的:

>>> a = {'key1' : 'val1', 'key2' : 'val2'}
>>> b = frozenset(a.items())
>>> frozenset_restored_to_dict = dict(b)
>>> frozenset_restored_to_dict
{'key2': 'val2', 'key1': 'val1'}

否则(字典保留插入顺序),请使用元组。这样,可以在保留项目顺序的同时恢复字典,但是,具有不同排序的相同项目的元组将不相等。一种解决方法是在每次进行比较之前将元组传递给 freezeset 构造函数。

>>> a = {'key1' : 'val1', 'key2' : 'val2'}
>>> b = tuple(a.items())
>>> tuple_restored_to_dict = dict(b)
>>> tuple_restored_to_dict
{'key1': 'val1', 'key2': 'val2'}

从代码中可以看出,b 是一个元组,或者是一个frozenset。两者都是不可变和可散列的,并且可以完全恢复为像a 这样的常规字典。

【讨论】:

  • 请注意,这要求字典值和键一样是可散列的。
  • 这将失去dict对象的最佳属性,即可以在恒定时间内实现按键查找。
  • @SomethingSomething,正如 BrentBam 所指出的,不适用于更复杂的示例,例如 {'a':[1,2],'b':{'c':[3,4,5],('d','e'):"blah"}}。如果存在映射到同一集合的不同类型,您必须递归冻结任何非哈希值,包括嵌套字典,并跟踪要解冻的类型。
【解决方案2】:

您可以尝试ordered dict 或查看以下答案:

PyPI 上甚至还有一个包:https://pypi.python.org/pypi/frozendict

您也可以简单地将 dict 转换为元组(sorted(your_dict.items())),然后用作哈希。

UPD:如 cmets 中所述,OrderedDict 是不可散列的。我的错,它真的不应该是可哈希的,因为它是可变的。

【讨论】:

  • OrderedDicts 也是不可散列的。
  • 请注意,可以使用 frozenset 代替 sorted 元组
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2018-07-05
  • 2016-09-20
  • 1970-01-01
  • 2019-12-05
  • 2016-10-19
  • 2011-05-07
相关资源
最近更新 更多