查看源代码,当前实现(3.7)
set_contains
显示在检查集合中的成员身份时确实将集合对象转换为冻结集合:
static int
set_contains(PySetObject *so, PyObject *key)
{
PyObject *tmpkey;
int rv;
rv = set_contains_key(so, key);
if (rv < 0) {
if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
return -1;
PyErr_Clear();
tmpkey = make_new_set(&PyFrozenSet_Type, key);
if (tmpkey == NULL)
return -1;
rv = set_contains_key(so, tmpkey);
Py_DECREF(tmpkey);
}
return rv;
}
基本上,如果给定的对象是一个集合(
PySet_Check(key)
,然后创建新的冻结集(
make_new_set(&PyFrozenSet_Type, key)
)再次检查会员资格(
set_contains_key(so, tmpkey)
)我不认为这实际上是在任何地方记录的,而且它可能是一个“只起作用”的特性,而您甚至没有注意到如果您不认真考虑它。
它似乎和被拒绝的人有着同样的精神
PEP-0351
,尽管它不是基于任何特殊方法的,并且仅限于集。
编辑:更详细的信息,这个功能显然是在2003年首次实现的。(
commit
通过
Raymond Hettinger
应
Alex Martelli
. 所以如果他们中的一个恰好在附近,也许他们可以提供更多的背景。
编辑2:值得注意的是,在特定情况下,这可能会对性能产生重大影响:
s = set(range(100000))
sf = frozenset(s)
t = { sf }
%timeit sf in t # True
>>> 31.6 ns ± 1.04 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit s in t # True
>>> 4.9 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
测试是
五
在第二种情况下,数量级变慢!
编辑3:I
raised an issue
对于python团队来说,讨论取消这种行为的可能性,因为它看起来不一致并且可能有问题。开发人员认为它仍然是一个有用的特性,缺点不值得破坏兼容性。