列表不可用,但元组可以清除?

时间:2016-05-10 11:12:22

标签: python list python-2.7 hash tuples

How to hash lists?我被告知我应该首先转换为元组,例如[1,2,3,4,5](1,2,3,4,5)

所以第一个不能被哈希,但第二个可以。为什么 *

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

6 个答案:

答案 0 :(得分:42)

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

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

现在,当您l.append(4)时会发生什么?您已修改字典中的密钥!远道而来!如果您熟悉散列算法的工作方式,这应该会让您感到害怕。另一方面,元组绝对是不可变的。 t += (1,)可能看起来像修改元组,但实际上并非如此:它只是创建一个 new 元组,保持字典键不变。

答案 1 :(得分:7)

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

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]会为您'Hello',但d[[23,42,99,7]]d[List([23,42,99,7])]都不会(因为您正在创建新的[Ll]ist

答案 2 :(得分:4)

由于列表是可变的,如果你修改它,你也会修改它的哈希值,这会破坏哈希(比如set或dict键)。

答案 3 :(得分:4)

因为列表是可变的而且元组不是。

答案 4 :(得分:1)

答案很好。原因是可变性。如果我们可以将字典中的list用作键; (或任何可变对象),那么我们就可以通过(意外或有意地)更改键来更改键。这将导致字典中键的哈希值发生变化,因此,我们将无法通过该键从该数据结构中检索该值。  通过将哈希值和哈希表映射到存储实数值条目的索引,可以轻松地映射大数据。

在此处详细了解它们:-

Hash TablesHash FunctionsAssosiative Arrays

答案 5 :(得分:0)

并非每个元组都是hashable。例如,元组包含list作为元素。

x = (1,[2,3])
print(type(x))
print(hash(x))