python - 在 Python 中,为什么元组是可哈希的,而列表却不能?

标签 python

在下面,当我尝试对列表进行哈希处理时,它给了我一个错误,但适用于元组。猜想这与不变性有关。谁能详细解释一下吗?

列表

 x = [1,2,3]
 y = {x: 9}
  Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: unhashable type: 'list'

元组

z = (5,6)
y = {z: 89}
print(y)
{(5, 6): 89}

最佳答案

字典和其他对象使用hashes快速存储和检索元素。这一切的机制都发生在“幕后”——作为程序员,你不需要做任何事情,Python 会在内部处理这一切。基本思想是,当您使用 {key: value} 创建字典时,Python 需要能够对您用于 key 的任何内容进行哈希处理,以便它可以存储和查找值很快。

不可变对象(immutable对象)或无法更改的对象是可散列的。它们有一个永不改变的唯一值,因此 python 可以“散列”该值并使用它来有效地查找字典值。属于这一类的对象包括字符串、元组、整数等。您可能会想,“但是我可以更改字符串!我只需执行 mystr = mystr + 'foo'”,但实际上这只是创建一个字符串实例并将其分配给mystr。它不会修改现有实例。不可变对象(immutable对象)永远不会改变,因此您始终可以确定,当您为不可变对象(immutable对象)生成哈希时,通过其哈希查找该对象将始终返回与您开始时相同的对象,而不是修改后的版本。

您可以自己尝试一下:hash("mystring"), hash(('foo', 'bar')), hash(1 )

可变对象,或可以修改的对象,不可散列。可以就地修改列表:mylist.append('bar')mylist.pop(0)。您无法安全地散列可变对象,因为您无法保证该对象自上次看到它以来没有发生更改。您会发现 listset 和其他可变类型没有 __hash__() 方法。因此,您不能使用可变对象作为字典键:

>>> hash([1,2,3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Eric Duminil的答案提供了一个很好的例子,说明使用可变对象作为字典键所产生的意外行为

关于python - 在 Python 中,为什么元组是可哈希的,而列表却不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59198348/

相关文章:

python - 阻止 Python 在 shebang 中生成 pyc 文件

python - 迭代 groupby 数据帧以在每一行中进行操作

python - 从数组中获取所需的列索引并将这些列添加到数据框中

2个字典列表的Python交集

python - 没有 dtype ('<U1' 的转换路径)问题

python - docker 在 python 循环中执行 time.sleep(1) 时卡住

python - 获取多维 NumPy 数组中最大值的位置

python - functools.wraps 和 update_wrapper 有什么区别

python - 如何解决这个问题(Pytorch RuntimeError : 1D target tensor expected, multi-target not supported)

Python - 在下一个代码中使用打印