2014-05-09 60 views
-1

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

hlst是一个列表。 备忘录是字典。

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

当我尝试它时,python告诉我,hlist不可用。

+3

不知道你在问什么。你的问题不清楚。 – thefourtheye

+0

如果'hlst'是一个列表,它不可能位于字典中。那你为什么要检查? (如果你想为字典添加一个列表,首先用'tuple(hlst)'将它变成一个元组:只要确保在把它用作关键字或检查它之前,你总是把任何其他的值变成一个元组存在) –

+0

不能附加一个字典,如果这就是你的意思。也许你想添加一个字典到列表? – aIKid

回答

0

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

为了克服这个问题,你可以根据darkryder的评论将你的列表变成一个元组tuple(hlist)

+0

问题是,它可能实际上是一个包含列表列表的元组。如何转换所有级别?另外,常规类的实例是可散列的,你也可以改变它们。 – Adam

1

你的问题是缺乏“可排除”概念的不妥协。

如果您能够计算哈希码,我们称之为对象“可哈”。

Hashcode(又名哈希函数)是一个函数,它接受一些对象并返回一些USUALLY应该足以区分它与其他对象的值。这意味着,某些点的哈希码应该可用作ID。当然,会有所谓的“散列冲突”(当两个对象具有相同的散列码时),因为存在比散列码更多的可能对象。

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

外观:我们有物品a,其中有属性/属性xy。要使散列函数正常工作,您需要确保散列函数不依赖于xy

列表具有取决于其值hashcodes的哈希码,所以它们本身是不可哈哈的。为什么?因为如果你改变列表中的一个元素(或添加一个或删除等),其哈希码将改变(因为它取决于这个元素)。

现在回到字典。字典是一个哈希表,它可以被描述为“简单的内存数组对,在索引下(X模数(数组大小))具有值,第一项具有哈希码X”(这是相当简单的,但主要概念坚持通过语言和实现;对的第一个值称为“key”,第二个“value”或“item”)。如果要插入带有散列码1234的列表[A,B],并将值V插入大小为10的散列表,然后将此列表的值更改为[A,C](这意味着将haschode更改为5678),然后在插入对时刻([A,B],V)将去在索引1234模10 = 4,但改变后它应该是在索引5678模10 = 8

为了使其正常工作,我们将每次关键对象发生变化(这很丑陋,难以实现并且会消耗大量资源)时需要通知哈希表,或者确保该键的哈希码不会像哈希表那样长时间变化。 Python创作者选择第二种选择,因为它被广泛使用,被证明工作良好并且稳定。

这是python有两个有序集合类型 - 列表和元组的原因之一。正如你可能知道的那样,元组是不可变的,所以它的哈希码不会改变 - 但是,它可能被用作字典键。

PS。上面的文字相当简单。列表哈希码依赖于它的元素是有点棘手。另外,字典作为散列表的实现没有在语言引用中定义 - 它只说明键应该是可散列的,并不能解释为什么。对于某些实现来说,可以很好地处理不可哈哈哈的对象,但是为了遵从引用强制可散列键。

相关问题