类型错误:不可哈希类型
我想得到一个包含元组的列表,像这样 [ [(1,0),(2,0),(3,0)],[(1,1),(2,1),(3,1)....]]
。我用了这个语句:
set([(a,b)for a in range(3)]for b in range(3))
但是它给了我一个错误。
TypeError: unhashable type: 'list'
我有两个问题想请教Python高手:
a) 当我查看Python中关于可哈希(Hashable)的定义时:
“一个对象是可哈希的,如果它在生命周期内有一个永远不变的哈希值(它需要有一个 hash() 方法)”
当我对上面的表达式使用 dir
函数时:
dir([(a,b)for a in range(3)]for b in range(3))
它似乎显示 __hash__
是存在的。那么,为什么我会得到错误呢?
我通过使用列表命令成功得到了 [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]
:
list(list((a,b) for a in range(3)) for bin range(3))
b) 列表和集合都接受可迭代对象作为参数。为什么一个可以用(列表),而另一个不可以(集合)呢?
6 个回答
列表是不可哈希的,因为它的内容在使用过程中可以随时改变。你可以随时更新列表中的某个项目。
列表在索引时不使用哈希,所以它里面的项目不需要是可哈希的,也就是说可以包含任何类型的内容。
总结:
- 你不能把列表、集合或字典进行哈希处理,然后把它们放进集合里。
- 你可以把元组进行哈希处理,这样就可以放进集合里。
举个例子:
>>> {1, 2, [3, 4]}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> {1, 2, (3, 4)}
set([1, 2, (3, 4)])
需要注意的是,哈希处理有点像递归,上面的说法对于嵌套的项目也是适用的:
>>> {1, 2, 3, (4, [2, 3])}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
字典的键也是可以进行哈希处理的,所以上面的说法同样适用于字典的键。
你正在通过 set(...)
来创建一个集合,而集合需要的是可以哈希的元素。也就是说,集合里不能放列表,因为列表是不可哈希的。
[[(a,b) for a in range(3)] for b in range(3)]
这是一个列表。它不是一种哈希类型。你在 dir(...)
看到的 __hash__
其实不是一个方法,它的值就是 None。
列表推导式会返回一个列表,你不需要特别使用 list,直接用就可以了:
>>> [[(a,b) for a in range(3)] for b in range(3)]
[[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]
试试这些:
>>> a = {1, 2, 3}
>>> b= [1, 2, 3]
>>> type(a)
<class 'set'>
>>> type(b)
<class 'list'>
>>> {1, 2, []}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> print([].__hash__)
None
>>> [[],[],[]] #list of lists
[[], [], []]
>>> {[], [], []} #set of lists
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'