即使集合不可删除,其他集合中的成员资格检查也是如此:
>>> set() in {frozenset()}
True
我期望TypeError: unhashable type: 'set'
,与Python中的其他行为一致:
>>> set() in {} # doesn't work when checking in dict
TypeError: unhashable type: 'set'
>>> {} in {frozenset()} # looking up some other unhashable type doesn't work
TypeError: unhashable type: 'dict'
那么,如何在其他集合中设置成员身份?
答案 0 :(得分:7)
set_contains
是implemented like this:
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;
}
因此,这将直接委托给set_contains_key
,它将基本上散列对象,然后使用其散列查找元素。
如果对象不可删除,set_contains_key
会返回-1
,因此我们进入if
。在这里,我们检查显式传递的key
对象是一个集合(或一个集合子类型的实例)和我们以前是否遇到类型错误。这表明我们尝试使用set
进行包含检查,但失败了,因为它不可用。
在这种情况下,我们现在从frozenset
创建一个新set
并再次使用set_contains_key
尝试进行包含检查。而且由于frozensets可以适当地清洗,我们能够以这种方式找到我们的结果。
这解释了为什么以下示例即使集合本身不可清除也能正常工作:
>>> set() in {frozenset()}
True
>>> set(('a')) in { frozenset(('a')) }
True
答案 1 :(得分:5)
the documentation for set
s的最后一行讨论了这个问题:
注意
__contains__()
,remove()
和discard()
的elem
参数 方法可以是set
。支持搜索等效项frozenset
,从elem
创建一个临时的。{/ p>