300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > python集合的元素可以是_Python集合的元素中 为什么不可以是包含嵌套列表的元组?...

python集合的元素可以是_Python集合的元素中 为什么不可以是包含嵌套列表的元组?...

时间:2018-07-07 14:29:42

相关推荐

python集合的元素可以是_Python集合的元素中 为什么不可以是包含嵌套列表的元组?...

你有一个误解,hash算法针对的是元素的内容,并不是针对指针,所以指针不变不等于可hash。

如果你想深究细节的话,可以看tuple的源码:

static Py_hash_t

tuplehash(PyTupleObject *v)

{

Py_uhash_t x; /* Unsigned for defined overflow behavior. */

Py_hash_t y;

Py_ssize_t len = Py_SIZE(v);

PyObject **p;

Py_uhash_t mult = _PyHASH_MULTIPLIER;

x = 0x345678UL;

p = v->ob_item;

while (--len >= 0) {

y = PyObject_Hash(*p++);

if (y == -1)

return -1;

x = (x ^ y) * mult;

/* the cast might truncate len; that doesn't change hash stability */

mult += (Py_hash_t)(82520UL + len + len);

}

x += 97531UL;

if (x == (Py_uhash_t)-1)

x = -2;

return x;

}

注意这里有一个循环,tuple会对其中每个元素调用PyObject_Hash,将结果进行异或运算再加上一个常量作为整个tuple的hash。

如果tuple中有一个元素是list,那么PyObject_Hash将调用list的hash算法,然而list定义就表明它根本不实现hash:

PyTypeObject PyList_Type = {

PyVarObject_HEAD_INIT(&PyType_Type, 0)

"list",

sizeof(PyListObject),

0,

(destructor)list_dealloc, /* tp_dealloc */

0, /* tp_print */

0, /* tp_getattr */

0, /* tp_setattr */

0, /* tp_reserved */

(reprfunc)list_repr, /* tp_repr */

0, /* tp_as_number */

&list_as_sequence, /* tp_as_sequence */

&list_as_mapping, /* tp_as_mapping */

PyObject_HashNotImplemented, /* tp_hash */

...

再看 PyObject_HashNotImplemented 的实现:

Py_hash_t

PyObject_HashNotImplemented(PyObject *v)

{

PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",

Py_TYPE(v)->tp_name);

return -1;

}

这个信息很眼熟吧?

结论就是,只要tuple中有一个元素是不可hash的(不限于list),那么整个tuple都是不可hash的。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。