A pesar de que los conjuntos son inestables, la verificación de membresía en otros trabajos de conjuntos:
>>> set() in {frozenset()} True
Esperaba TypeError: unhashable type: 'set'
, consistente con otros comportamientos en 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'
Entonces, ¿cómo se implementa la pertenencia a otro conjunto?
La última línea de la documentación para el set
s trata esto:
Tenga en cuenta que el argumento
elem
de los__contains__()
,remove()
ydiscard()
puede ser unset
. Para apoyar la búsqueda de unfrozenset
equivalente, se crea uno temporal desdeelem
.
set_contains
se implementa de esta manera :
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; }
Por lo tanto, esto delegará directamente a set_contains_key
lo que esencialmente hará un hash del objeto y luego buscará el elemento usando su hash.
Si el objeto es inestable, set_contains_key
devuelve -1
, así que nos set_contains_key
dentro de eso if
. Aquí, verificamos explícitamente si el objeto key
pasado es un conjunto (o una instancia de un subtipo de conjunto) y si previamente obtuvimos un error de tipo. Esto sugeriría que intentamos una verificación de contención con un set
pero que falló porque es inestable.
En esa situación exacta, ahora creamos un nuevo frozenset
partir de ese set
e intentamos la verificación de la contención usando set_contains_key
nuevamente. Y como los frozensets son hashables correctamente, podemos encontrar nuestro resultado de esa manera.
Esto explica por qué los siguientes ejemplos funcionarán correctamente a pesar de que el conjunto en sí no es hashable:
>>> set() in {frozenset()} True >>> set(('a')) in { frozenset(('a')) } True