例如,元组(1,[0,1,2])
.从设计的角度来看,我理解为什么;如果元组仍然是可哈希的,那么通过将任何不可哈希类型包装在元组中来使任何不可哈希类型可哈希是微不足道的,这破坏了哈希性的正确行为,因为您可以在不更改元组的哈希值的情况下更改对象的值。但是如果元组不是可哈希的,那么我不明白是什么使对象可哈希 - 我认为它只需要实现__hash__(self)
,元组可以。
根据我看过的其他答案和测试示例,这样的对象似乎是不可哈希的。似乎明智的行为是让tuple.__hash__()
为其组件对象调用__hash__
,但我不明白从实现的角度来看这将如何工作,例如,我不知道字典如何将其识别为不可哈希类型时它仍然是元组类型并且元组仍然定义__hash__
。
tuple
通过计算和组合其包含的值的哈希来实现自己的哈希。当哈希处理其中一个值失败时,它会让生成的异常不受阻碍地传播。
不可散列只是意味着调用hash()
触发TypeError
;一种方法是不定义__hash__
方法,但如果在__hash__
方法的过程中你通过其他方式引发TypeError
(或任何其他错误),它同样有效。
基本上,tuple
是可哈希类型(isinstance((), collections.abc.Hashable)
是正确的,isinstance(([],), collections.abc.Hashable)
也是如此,因为它是对是否存在 __hash__
的类型级别检查),但如果它存储不可哈希类型,任何计算哈希的尝试都会在使用时引发异常,因此在这种情况下它的行为类似于不可哈希类型。
我假设tuple.__hash__()
对元组中的每个项目调用hash(item)
,然后将结果一起 XOR。如果其中一个项目不可哈希处理,则会引发一个冒泡到原始调用方的TypeError
。