为何包含可变元素的tuple无法作为set元素或dictionary的键?
为什么包含可变对象的元组不能作为集合元素或字典键
首先需要纠正一个核心认知误区:你认为「元组的哈希值基于内部元素的引用ID计算」是不符合Python的设计规则的。
可哈希对象的必备条件
Python中所有可以作为集合元素、字典键的对象,必须同时满足两个要求:
- 自身的哈希值在整个生命周期中不会发生变化
- 若两个对象通过
==判断为相等,则两者的哈希值一定相等
元组的哈希计算逻辑
元组作为容器类型,它的哈希值是递归对所有内部元素的哈希值做组合运算得到的,不是基于元素的引用ID计算。只要元组内部存在任意一个不可哈希的元素,整个元组就无法计算出合法的哈希值,自然无法存入集合或作为字典键。
你给出的示例代码:
tuple = (1, "mayank", [1, "mayank"]) set = {1, "mayank", tuple}
报错的直接原因就是计算上述元组的哈希值时,需要先计算内部列表[1, "mayank"]的哈希,而列表本身是可变、不可哈希的类型,所以直接抛出TypeError: unhashable type: 'list'。
为什么不设计为按引用计算元组哈希?
如果强行修改规则,让包含可变元素的元组按内部元素的引用ID计算哈希,会和Python现有元组的相等性判断逻辑产生本质冲突:
当前Python中元组的==判断是按内容递归比较的,比如(1, [2]) == (1, [2])的执行结果为True,如果哈希按引用计算,就会出现两个相等的元组哈希值完全不同的情况,彻底违反可哈希对象的基本规则,会导致字典、集合的存取逻辑完全混乱,出现大量明明键存在却找不到的反直觉问题。
内容的提问来源于stack exchange,提问作者mayank mahajan
相关产品推荐
相关产品推荐

