gpt4 book ai didi

python - x 不在集合中与 x != 集合中的每个元素?

转载 作者:太空狗 更新时间:2023-10-30 02:01:29 24 4
gpt4 key购买 nike

假设我们有 x = ['a', 'b']

声明的幕后情况:

x not in {None, False}

这引发了 unhashable type: 'list' 错误?

我找到的解决方法是改写这个:

x != None and x!= False

但我很困惑,因为在数学上,两个 bool 表达式是等价的。

最佳答案

理由

官方文档是这样写的:

  1. [Python 3]: class set([iterable]) :

    Return a new set or frozenset object whose elements are taken from iterable. The elements of a set must be hashable.

  2. [Python 3]: hashable :

    An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method). Hashable objects which compare equal must have the same hash value.
    ...
    All of Python’s immutable built-in objects are hashable; mutable containers (such as lists or dictionaries) are not.

  3. [Python 3]: object.__contains__(self, item) (就在 anchor 上方):

    The membership test operators (in and not in) are normally implemented as an iteration through a sequence. However, container objects can supply the following special method with a more efficient implementation, which also does not require the object be a sequence.

进入[GitHub]: python/cpython - (v3.5.4) cpython/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;
    }

从“调用堆栈”(以相反顺序呈现)可以看出,为了测试成员资格(in/not in),hash 正在对候选成员(“includee”)执行(在所有代码路径上),并且由于 list 实例没有 hash 功能,解释器吐出 TypeError

决议

有很多方法可以解决这个问题(正如许多其他人已经指出的那样):

  • 使用不要求其元素可哈希的容器(列表元组)
  • 测试__hash__成员
  • 将成员资格测试包装在try/except block 中
  • 为元素使用可散列的容器(元组):x = ('a', 'b')

但是(通常)这些只是解决问题的方法(这是我个人的意见),因为如果您最终将列表与None 和< em>错误,代码(生成该列表)可以使用一些重构。

关于python - x 不在集合中与 x != 集合中的每个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49258986/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com