How/why {frozenset()} 中的 set() 有效吗?
How/why does set() in {frozenset()} work?
即使集不可散列,其他集的成员资格检查也有效:
>>> 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'
那么,其他集合中的集合成员是如何实现的?
the documentation for set
s 的最后一行讨论了这个:
Note, the elem
argument to the __contains__()
, remove()
, and discard()
methods may be a set
. To support searching for an equivalent
frozenset
, a temporary one is created from elem
.
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
returns -1
,所以我们进入那个 if
。在这里,我们检查显式传递的key
对象是否是集合(或集合子类型的实例)和我们之前是否出现类型错误。这表明我们尝试使用 set
进行包含检查,但失败了,因为它不可散列。
在那种情况下,我们现在从 set
创建一个新的 frozenset
并再次尝试使用 set_contains_key
进行收容检查。由于 frozensets 是可适当散列的,因此我们能够以这种方式找到我们的结果。
这解释了为什么即使集合本身不可哈希,以下示例也能正常工作:
>>> set() in {frozenset()}
True
>>> set(('a')) in { frozenset(('a')) }
True
即使集不可散列,其他集的成员资格检查也有效:
>>> 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'
那么,其他集合中的集合成员是如何实现的?
the documentation for set
s 的最后一行讨论了这个:
Note, the
elem
argument to the__contains__()
,remove()
, anddiscard()
methods may be aset
. To support searching for an equivalentfrozenset
, a temporary one is created fromelem
.
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
returns -1
,所以我们进入那个 if
。在这里,我们检查显式传递的key
对象是否是集合(或集合子类型的实例)和我们之前是否出现类型错误。这表明我们尝试使用 set
进行包含检查,但失败了,因为它不可散列。
在那种情况下,我们现在从 set
创建一个新的 frozenset
并再次尝试使用 set_contains_key
进行收容检查。由于 frozensets 是可适当散列的,因此我们能够以这种方式找到我们的结果。
这解释了为什么即使集合本身不可哈希,以下示例也能正常工作:
>>> set() in {frozenset()}
True
>>> set(('a')) in { frozenset(('a')) }
True