为何set()可存在于{frozenset()}?不可哈希集合成员检查为何正常?
问题2:为什么用不可哈希的set在另一个集合中做成员检查时,有时不会触发TypeError?
你的预期其实是对的:正常情况下,用不可哈希的对象(比如set、列表)做集合的成员检查,一定会触发TypeError,因为集合是基于哈希表实现的——执行x in s时,Python首先会尝试计算x的哈希值来定位哈希桶,而不可哈希的对象会在这一步直接报错,比如:
>>> [] in {1, 2} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' >>> set() in {1, 2} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set'
那为什么你会看到成员检查“正常运行”?这里可能存在几种误解:
- 混淆了容器类型:如果你是在列表(而不是集合)中做成员检查,比如
set() in [frozenset()],这确实会返回False而不报错——因为列表的成员检查是遍历所有元素逐个比较,不需要依赖哈希值。 - 混淆了操作类型:如果你用的是子集检查(比如
set().issubset({frozenset()})),这也不会报错,但这不是成员检查,而是判断一个集合是否是另一个集合的子集,逻辑完全不同。 - 特殊场景的误判:假设你有一个集合包含
frozenset([1,2]),然后检查set([1,2]) in 这个集合——哪怕set([1,2]) == frozenset([1,2])返回True,这个成员检查依然会报错,因为Python必须先计算set的哈希值,而set不可哈希。
总结一下:集合的成员检查必须依赖被检查对象的哈希值,所以不可哈希的set在集合中做成员检查时,一定会触发TypeError,这和Python的行为逻辑完全一致。如果你看到了“正常运行”的情况,大概率是混淆了容器或操作类型。
内容的提问来源于stack exchange,提问作者wim
相关产品推荐
相关产品推荐

