python - 为什么可变数据类型生成的哈希码不能成为python中的字典键?
问题描述
我已经阅读了许多关于字典键不可变的 stackoverflow 答案。
我读了下面的答案,比如
下面是我的理解
当我们执行类似的操作时,会在完成检索的帮助下为每个字典键生成一个哈希码
d["name"]
,这使得它比列表或元组更有效,因为它知道它在内存中的位置。如果可变数据类型被允许作为字典键,如果键更改将生成新的哈希码,并且字典将无法找到此哈希码,因为哈希码已更改并且它没有内存。
我的问题是,为什么字典不能存储这个新的哈希码并在检索过程中使用它。为什么这是不可接受的,它的缺点是什么?
如果我不清楚我的问题,请告诉我,我缺少什么,将更具描述性。
提前致谢!
解决方案
实际上,您可以在 Python 中制作可变键;下面的代码是一个例子。您真的不想这样做,因为您无法访问字典条目,因此开发人员通常会确保他们的可变类型在您尝试将实例设为键时抛出一些错误。
你问为什么字典不能只重新计算哈希码,所以可变键永远不会失去对其值的访问权。好吧,看看这个例子。突变badKey.data = 20
与 无关myDict
,因此myDict
不知道重新散列。
当键发生突变时,假设可以对字典进行重新散列,但它要求字典是键的一部分。这只会让人头疼:
badKey
必须循环包含myDict
which containsbadKey
,这是垃圾收集器的额外工作,badKey
可以在多个字典中,因此badKey
必须包含所有字典,- 当您可以使用
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
推荐阅读
- node.js - React:使用 Next.js 上传损坏的分块文件
- java - 如何存储我从上一个屏幕获得的 lastid 并获取该 id 并单击下一个选项卡中的 id
- mysql - 提高 SQL 性能:多次插入或更新多个表
- pyspark - pyspark collect_list() 和 collect_set() 使用 groupByKey 还是使用 reduceByKey?
- git - 如何使用“git checkout -d”?
- groovy - groovy中的转置列表
- postgresql - PostgreSQL:从选择中插入的一些麻烦与冲突
- python - 序列化 Django RawQuery 的推荐方式
- java - 获取 :: java.lang.NoSuchMethodError: org.apache.xmlbeans.XmlOptions.put(Ljava/lang/Object;)V
- macos - 在钥匙串 MacOS 中找不到 github