python - Why does set() in set() not raise a TypeError, unlike {} in set(), [] in set(), set() in {}, [] in {}, or {} in {}?
问题描述
Sets and dicts are unhashable thus can't contain sets, dicts, or lists as keys. Even checking for containment raises a TypeError, as in all these five cases:
{} in {}
[] in {}
set() in {}
{} in set()
[] in set()
but checking if a set contains a set does not raise a TypeError:
set() in set()
returns False.
Why is set() in set()
handled differently from {} in {}
, [] in {}
, set() in {}
, {} in set()
, or [] in set()
?
解决方案
Good question! It doesn't appear to be documented, but staring at the implementation code it does appear to be intentional. While sets can't contain sets, they can contain frozensets. For example,
>>> s = {frozenset({2, 3}), frozenset({5, 7})}
>>> s
{frozenset({2, 3}), frozenset({5, 7})}
>>> type(s)
<class 'set'>
So s
contains frozensets, but is not itself a frozenset. Now in this:
>>> {7, 5} in s
True
the implementation of set.__contains__()
first tries to see whether {7, 5}
is in s
. That raises a TypeError
("key not hashable") internally. If checking for a key raises a type error, and the key is of a set type, then the implementation clears that error, builds a temporary frozenset from the original key, and tries again.
Offhand, I would not have done that (too magical), but perhaps there was some compelling use case I'm unaware of.
Correction
It is documented, but as the very last line of the set
docs:
Note, the elem argument to the
__contains__()
,remove()
, anddiscard()
methods may be a set. To support searching for an equivalent frozenset, a temporary one is created from elem.
推荐阅读
- interrupt - MSP430:尝试使用按钮和 LED 闪烁来学习中断
- powershell - 难以模拟 Invoke-WebRequest 的 BasicHtmlWebResponseObject
- angular - 在 ng-select 中显示 '>' 和 '<' 符号
- c# - 在 ASP.Net Core Razor 页面中使用会话包装器
- javascript - 在 Javascript 号码上使用 bind() 时,console.log() 输出代表什么?
- angular - 可观察到的特殊结果:使用 Jasmine 弹珠进行测试
- wordpress - 在 Wordpress 的 s2Member 中更新 Paypal API 签名时是否有任何“陷阱”?
- python - 如何在python中读取用空格分隔的json对象的文本文件
- java - 简化嵌套 if else 循环 Java 中的认知复杂性
- typescript - 如何使用 TypeScript 泛型函数来强制传入的类型上存在的属性?