众所周知,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的数据要求类型啊。
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__()
函数实现。会计算所有元素的哈希值。
其实就是
tuple
的hash值,是根据其里面所有元素的hash值确定的。如: