【发布时间】:2015-05-29 19:32:46
【问题描述】:
一个可散列的对象需要一个__hash__ 方法,并且它有一个在其生命周期内永远不会改变的散列值。
由于我完全忽略的原因,Python 列表不可散列,我想知道以下实现是否正常,或者它是否有一些我不知道的故障。
class L(list):
def __hash__(self):
return id(self)
a = range(10)
l = L(range(10))
print a
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print l
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
hash(l)
>> 41889288
hash(a) # unsurprisingly it returns an error because a list is not hashable
>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
# lets append a value to l
l.append(1000)
print l
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000]
isinstance(l, list) # to double check whether l is a List instance
>> True
D = {}
D[l] = "this is a dict with a list as key"
print D
{[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000]: 'this is a dict with a list as key'}
# lets append another value to l
l.append(-10)
print D
>> {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000, -10]: 'this is a dict with a list as key'}
# now lets add a normal list to the dict to the dict
D[a] = "Add a list as key"
>>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
所以这是一个可散列的列表实现,几乎没有问题,我不明白为什么一个列表在正常的 Python 发行版中不能是可散列的,即使它仍然是可变的。
注意:这个问题不是关于为什么列表不能用作字典键 有什么解释吗?
【问题讨论】:
-
什么是可散列和可变的?如果列表改变而哈希没有改变,你怎么能有意义地将它用作字典键?字典和哈希表的整个概念在这里分解。哈希是用来区分一个键和另一个键的。如果 key 改变了而 hash 没有改变,那会发生什么?
-
换句话说,根据你的想法,假设我创建了一个字典
d,并分配d[[1,2,3]] = 'alpha'。 (也就是说,键[1, 2, 3]指的是'alpha'。)然后我追加到列表中。d[[1, 2, 3, 4]]仍然是 alpha 吗?如果我创建一个新列表[1, 2, 3, 4],它可能具有不同的哈希值,然后将其添加到字典中怎么办?然后呢? -
从技术上讲,您是对的,但如果您将其视为实例,则密钥不会改变。它的值在变化,但实例本身没有变化
-
谷歌搜索“python 列表作为字典键”让我找到了this SO question,这让我找到了this Python Wiki entry,很好地解释了为什么像
list这样的可变数据类型不是一个好的选择用于字典键。 -
它是可散列的point是什么?列表不是不可散列的,因为它很难,而是因为它没有意义。
标签: python python-2.7 mutable hashable