在下面,当我尝试对列表进行哈希处理时,它给了我一个错误,但适用于元组。猜想这与不变性有关。谁能详细解释一下吗?
列表
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)
。您无法安全地散列可变对象,因为您无法保证该对象自上次看到它以来没有发生更改。您会发现 list
、set
和其他可变类型没有 __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/