为什么我不能用列表作为字典的关键字?

2024-09-26 22:54:06 发布

您现在位置:Python中文网/ 问答频道 /正文

为什么我不能用列表作为字典的关键字?在

hlst是一个列表。 备忘录是口述

if not hlst in memo:
    # do something
else:
    configurations = memo[hlst]

当我尝试时,python告诉我hlist是不可更改的。在


Tags: in列表if字典not关键字备忘录do
2条回答

你的问题是缺乏对“散列”概念的不理解。在

如果你能计算出对象的hashcode,我们称之为“hashable”。在

Hashcode(又称hash函数)是一个接受对象并返回一些值的函数,这些值通常足以将它与其他对象区分开来。这意味着,hashcode在某种程度上应该可以作为ID使用,当然,会出现所谓的“hash conflicts”(当两个对象具有相同的hashcode时),因为可能的对象比hashcode多得多。在

对散列函数(用于获取对象haschode的函数)的约束(比“不同的对象有不同的hashcode”)更重要的是,它在对象的整个生命周期中应该是相同的。在

看:我们有对象a,它有属性/属性x和{}。要使散列函数正常工作,您需要确保a的散列不依赖于x和{}。在

列表的hashcode依赖于其值hashcode,因此它们本身是不可损坏的。为什么?因为如果你改变了list的一个元素(或者add,remove,等等),它的hashcode也会改变(因为它依赖于这个元素)。在

现在,回到字典。Dictionary是一个散列表,可以描述为“在内存中简单的成对数组,在索引(X modulo(array size))下有值,其中第一个项有hashode X”(这是一个相当简单的方法,但主要概念贯穿语言和实现;对的第一个值称为“key”,第二个“value”或“item”)。如果要将哈希码为1234且值为V的列表[A,B]插入到大小为10的哈希表中,然后将该列表的值更改为[A,C](这意味着haschode更改为5678),则在插入对时([A,B],V)将在索引1234模10=4处执行,但更改后应位于索引5678模10=8处。在

为了使其正常工作,我们需要在每次key对象发生变化时通知hash table(这很难看,很难实现,并且占用大量资源),或者确保key的hashcode不会像hash table中那样长时间地更改。Python的创建者选择了第二种选择,因为它被广泛使用,并且被证明工作良好且稳定。在

这就是python有两种有序集合类型的原因之一——列表和元组。正如您可能知道的,元组是不可变的,所以它的哈希代码不应该更改-因此,它可以用作字典键。在

以上文字相当简单。列表哈希代码对其元素的依赖性有点棘手。另外,dictionary作为hashmap的实现并没有在语言引用中定义——它只说明键应该是散列的,并没有解释为什么。有些实现可以很好地处理不易损坏的对象,但是为了符合引用,强制使用散列键。在

不能将列表用作键,因为列表是可变的。因为它们是可变的,所以它们不能是散列的(比如字符串和元组)。假设hlist = ['a']。想想如果您将hlist的内容更改为['b'],会发生什么。memo[['a']]会返回什么?在

为了克服这个问题,您可以根据darkryder的评论将列表转换为一个元组tuple(hlist)。在

相关问题 更多 >

    热门问题