首页 > 解决方案 > 为什么可变数据类型生成的哈希码不能成为python中的字典键?

问题描述

我已经阅读了许多关于字典键不可变的 stackoverflow 答案。

我读了下面的答案,比如

为什么字典键必须是不可变的?

下面是我的理解

  1. 当我们执行类似的操作时,会在完成检索的帮助下为每个字典键生成一个哈希码d["name"],这使得它比列表或元组更有效,因为它知道它在内存中的位置。

  2. 如果可变数据类型被允许作为字典键,如果键更改将生成新的哈希码,并且字典将无法找到此哈希码,因为哈希码已更改并且它没有内存。

我的问题是,为什么字典不能存储这个新的哈希码并在检索过程中使用它。为什么这是不可接受的,它的缺点是什么?

如果我不清楚我的问题,请告诉我,我缺少什么,将更具描述性。

提前致谢!

标签: pythonpython-3.x

解决方案


实际上,您可以在 Python 中制作可变键;下面的代码是一个例子。您真的不想这样做,因为您无法访问字典条目,因此开发人员通常会确保他们的可变类型在您尝试将实例设为键时抛出一些错误。

你问为什么字典不能只重新计算哈希码,所以可变键永远不会失去对其值的访问权。好吧,看看这个例子。突变badKey.data = 20与 无关myDict,因此myDict不知道重新散列。

当键发生突变时,假设可以对字典进行重新散列,但它要求字典是键的一部分。这只会让人头疼:

  1. badKey必须循环包含myDictwhich contains badKey,这是垃圾收集器的额外工作,
  2. badKey可以在多个字典中,因此badKey必须包含所有字典,
  3. 当您可以使用id(badKey)的唯一整数 IDbadKey或某些不可变版本的badKey有效键时,为什么还要麻烦这些呢?例如后者,您可以将列表的内容在某一点冻结为一个键的元组。
class badHasher:
    'hash value depends on an attribute; this is very bad'
    def __init__(self, something):
        self.data = something
    def __hash__(self):
        return hash(self.data)
    def __repr__(self):
        return 'badHasher(' + str(self.data) + ')'

badKey = badHasher(10)
myDict = {badKey: 'ten'}

# run below code line by line in REPL

print(myDict[badKey]) # ten

badKey.data = 20

print(myDict[badKey]) # KeyError: badHasher(20)

badKey.data = 10

print(myDict[badKey]) # ten

推荐阅读