X is not in the set versus x! = Every element in the set?

Assume that x = ['a', 'b'].

What happens under the hood for approval:

x not in {None, False}

which causes the error unhashable type: 'list'?

The workaround I found is as follows:

x != None and x!= False

but I got confused because mathematically both Boolean expressions are equivalent.

+4
source share
4 answers

Justification

Here is what the official documentation says:

Python 3.5.4 ($ {PYTHON_SRC_DIR}/Objects/setobject.c)

  • β„– 1991:

    static PyMethodDef set_methods[] = {
        {"add",             (PyCFunction)set_add,           METH_O,
         add_doc},
        {"clear",           (PyCFunction)set_clear,         METH_NOARGS,
         clear_doc},
        {"__contains__",(PyCFunction)set_direct_contains,           METH_O | METH_COEXIST,  // @TODO - cfati: MARK THIS LINE
    
  • # 1843:

    static PyObject *
    set_direct_contains(PySetObject *so, PyObject *key)
    {
        long result;
    
        result = set_contains(so, key);  // @TODO - cfati: MARK THIS LINE
        if (result == -1)
            return NULL;
        return PyBool_FromLong(result);
    }
    
  • β„– 1823:

    static int
    set_contains(PySetObject *so, PyObject *key)
    {
        PyObject *tmpkey;
        int rv;
    
        rv = set_contains_key(so, key);    // @TODO - cfati: MARK THIS LINE
        if (rv == -1) {
            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);  // @TODO - cfati: MARK THIS LINE
            Py_DECREF(tmpkey);
        }
        return rv;
    }
    
  • β„– 627:

    static int
    set_contains_key(PySetObject *so, PyObject *key)
    {
        setentry entry;
        Py_hash_t hash;
    
        if (!PyUnicode_CheckExact(key) ||
            (hash = ((PyASCIIObject *) key)->hash) == -1) {  // @TODO - cfati: MARK THIS LINE
            hash = PyObject_Hash(key);
            if (hash == -1)
                return -1;
        }
        entry.key = key;
        entry.hash = hash;
        return set_contains_entry(so, &entry);  // @TODO - cfati: MARK THIS LINE
    }
    
  • # 614:

    static int
    set_contains_entry(PySetObject *so, setentry *entry)
    {
        PyObject *key;
        setentry *lu_entry;
    
        lu_entry = set_lookkey(so, entry->key, entry->hash);  // @TODO - cfati: MARK THIS LINE
        if (lu_entry == NULL)
            return -1;
        key = lu_entry->key;
        return key != NULL && key != dummy;
    }
    

"callstack" ( ), (in/not in), hash ( ) - ( "includesee" ), list -, TypeError.

( ):

  • , , (list, tuple)
  • __hash__
  • try/except
  • (tuple) : x = ('a', 'b')

( ) ( ), None False, ( ) .

+5

, , set, , ( )

:

if x.__hash__ and x in {None,False}:

, x.__hash__ None ( : "" "hashable" Python), .

( , ):

def belongs(x):
    try:
        return x in {None,False}
    except TypeError:   # unhashable type
        return False

, list tuple ((None,False)), (.. , true )

+3

{None, False} - . , . .

. .

x not in (None, False)
+1

set vs list

__contains__ dunder ( ). ,

>>> 1 in [1,2] 

>>> list.__contains__([1,2],1)
>>> True

:

>>> [1,2] in [1,2,3]
>>> False #We get False instead of TypeError here

? - . Infact -. , Hash-Table. sets , .. O(1) list, O(n). , in , __contains__ hash , , __hash__. python, : TypeError: unhashable type: 'list'. , , .

In short membership tests, you cannot run on sets with a non-displayable object. Generally speaking, all volatile objects are (list, sets, dict)not shaken.

0
source

Source: https://habr.com/ru/post/1694817/


All Articles