python基础问题请教一下,dict的key可以是([1, 2],)这种类型的吗?

python基础问题请教一下,dict的key可以是([1, 2],)这种类型的吗?

众所周知,python的dict对象,是一个不可哈希对象,是可变的。他的key只接受 哈希类型 的数据,也就是 字符串、整型、浮点型、布尔、元组和None;而不可hash的有 字典、数组、集合是不能作为key的。

遇到一个疑问,没找到合理的解释,求释疑。

In [133]: a = {}

In [134]: a[(1, 2)] = 'abc'

In [135]: a

Out[135]: {(1, 2): 'abc'}

################

In [136]: a[([1, 2],)] = 'def'

---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

Cell In [136], line 1

----> 1 a[([1, 2],)] = 'def'

TypeError: unhashable type: 'list'

这里面报错的部分是字典的key出现了不可哈希对象,list

但是我用 ([1, 2],) 包裹了,这个整体应当是一个哈希对象才对,而且是 tuple 不是 list。应当符合字典key的数据要求类型啊。

python">In [138]: from typing import Hashable

In [139]: isinstance(([1, 2],), Hashable)

Out[139]: True

通过校验结果,可以看到 ([1, 2],) 确实是可哈希的。但上面那个报错我就不太理解,希望有大佬能提点一下,没找到官方解释。


另外,补充一个例子:

In [141]: class example(object):

...: def __init__(self, a):

...: self.value = a

...: def __eq__(self, rhs):

...: return self.value == rhs.value

...: def __hash__(self):

...: return hash(self.value)

...:

In [150]: a = example(2)

...: d = {a: "first"}

...: a.data = 2

...: d[a] = 'second'

In [151]: d

Out[151]: {<__main__.example at 0x10a5d3d30>: 'second'}

In [153]: isinstance(a, Hashable)

Out[153]: True

官方文档,看到hashable的定义:

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.

Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.

Most of Python’s immutable built-in objects are hashable; mutable containers (such as lists or dictionaries) are not; immutable containers (such as tuples and frozensets) are only hashable if their elements are hashable.

Objects which are instances of user-defined classes are hashable by default. They all compare unequal (except with themselves), and their hash value is derived from their id().


回答:

hashable: 对象的__hash__()函数。

看下tuple__hash__()函数实现。

https://github.com/python/cpy...
static Py_hash_t

tuplehash(PyTupleObject *v)

{

Py_ssize_t i, len = Py_SIZE(v);

PyObject **item = v->ob_item;

Py_uhash_t acc = _PyHASH_XXPRIME_5;

for (i = 0; i < len; i++) {

Py_uhash_t lane = PyObject_Hash(item[i]);

if (lane == (Py_uhash_t)-1) {

return -1;

}

acc += lane * _PyHASH_XXPRIME_2;

acc = _PyHASH_XXROTATE(acc);

acc *= _PyHASH_XXPRIME_1;

}

/* Add input length, mangled to keep the historical value of hash(()). */

acc += len ^ (_PyHASH_XXPRIME_5 ^ 3527539UL);

if (acc == (Py_uhash_t)-1) {

return 1546275796;

}

return acc;

}

会计算所有元素的哈希值。


其实就是tuple的hash值,是根据其里面所有元素的hash值确定的。如:

t1 = (1, 2, 3)

t1_hash = t1.__hash__()

# t1.__hash__() 这个值的计算

# 类似这种计算

def tuple_hash(t1):

t_hash = 0

for i in t1:

i_hash = i.__hash__()

# 为了避免哈希碰撞,做了一系列处理

t_hash += magic_func(i_hash)

return t_hash

以上是 python基础问题请教一下,dict的key可以是([1, 2],)这种类型的吗? 的全部内容, 来源链接: utcz.com/p/938682.html

回到顶部