列表不可散列,但元组可散列?

新手上路,请多包涵

如何哈希列表? 有人告诉我应该先转换为元组,例如 [1,2,3,4,5](1,2,3,4,5)

所以第一个不能散列,但第二个可以。为什么* ?


*我并不是真的在寻找详细的技术解释,而是在寻找直觉

原文由 gsamaras 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 535
2 个回答

主要是因为元组是不可变的。假设以下工作:

 >>> l = [1, 2, 3]
>>> t = (1, 2, 3)
>>> x = {l: 'a list', t: 'a tuple'}

现在,当您执行 l.append(4) 时会发生什么?您已经修改了字典中的键!远道而来!如果您熟悉散列算法的工作原理,这应该会吓到您。另一方面,元组是绝对不可变的。 t += (1,) 可能看起来它正在修改元组,但实际上它不是:它只是创建一个 的元组,让你的字典键保持不变。

原文由 val 发布,翻译遵循 CC BY-SA 3.0 许可协议

你完全可以做到这一点,但我打赌你不会喜欢这些效果。

 from functools import reduce
from operator import xor

class List(list):
    def __hash__(self):
        return reduce(xor, self)

现在让我们看看会发生什么:

 >>> l = List([23,42,99])
>>> hash(l)
94
>>> d = {l: "Hello"}
>>> d[l]
'Hello'
>>> l.append(7)
>>> d
{[23, 42, 99, 7]: 'Hello'}
>>> l
[23, 42, 99, 7]
>>> d[l]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: [23, 42, 99, 7]

编辑: 所以我想了更多。如果您返回列表的 id 作为它的哈希值,您可以使上面的示例工作:

 class List(list):
    def __hash__(self):
        return id(self)

在这种情况下, d[l] d[[23,42,99,7]] d[List([23,42,99,7])] 提供 'Hello' ,但都不 [Ll]ist

原文由 L3viathan 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题