如何修复TypeError: unhashable type: 'numpy.ndarray'?

2,198 阅读5分钟

所有的 Python 对象如字符串整数列表字典集合都有一个与之相关的可散列属性。有些对象是可散列的,而有些则不是。

当我们说一个Python对象是可散列的,这意味着该对象的值将保持不变,直到其寿命结束。例如,intfloat字符串

像列表、字典、集合和字节数组这样的 Python 对象是不可哈希的。意思是,这些对象的值可能会改变。例如,我们可以在这些对象中删除或添加一个元素。因此,值可能会改变。

了解TypeError的根本原因:unhashable类型:'numpy.ndarray'

在程序上,我们可以通过使用 [hash()](https://blog.finxter.com/python-hash-function/)函数。如果hash() ,返回一个数字,这表明该对象是可散列的。

比方说,我们有一个字符串。让我们看看当我们对字符串对象运行hash 函数时会发生什么。

s="Finxter"
print(hash(s))

输出

951412520483326359

当我们在一个字符串对象上运行hash() 函数时,会返回一个数字,表明它是一个可散列的对象。

现在,让我们看看当我们在一个ndarray 对象上运行哈希函数时会发生什么。

arr=np.array([1,2,3,4])
print(hash(arr))

输出

Traceback (most recent call last):
  File "C:\Users\...\unhashable_type_ndarray.py", line 18, in <module>
    print(hash(arr))
TypeError: unhashable type: 'numpy.ndarray'

我们看到一个错误,因为ndarray 对象不是可哈希的。

我知道你在想什么!

我的程序中没有hash() 函数。为什么我会看到这个错误?

这是因为你在程序中使用了字典或集合函数。而 dictionary keys设置元素必须是可哈希的。所以在内部,这些对象使用hash() 来验证你要添加的元素是否是可哈希的。关于更多细节,请查看集合字典的源代码。

我们在以下情况下看到TypeError: unhashable type: 'numpy.ndarray' ,。

  • 当我们把一个多维的ndarray 对象转换成一个集合对象时。
  • 当我们把一个ndarray 对象指定为一个字典键时。
  • 当我们把一个ndarray 对象添加到一个集合中时。

现在,让我们用一个例子来讨论这些情况中的每一种。

案例1:将一个多维的ndarray对象转换为一个set对象。

在 Python 中,一个可迭代对象可以使用 [set()](https://blog.finxter.com/python-set-function/)函数转换为集合对象。

注意,集合中的元素应该是强制性的可散列的。当我们在一个数组上调用set() 函数时,Python 解释器会检查该数组的元素是否是可散列的类型。如果是的话,ndarray 对象的元素就被转换为一个集合对象。

为了更好地理解这一点,让我们看一个例子。

import numpy as np

arr=np.array([1,2,3,4])
print(set(arr))

输出

{1, 2, 3, 4}

在上面的例子中,我们有一个数组[1,2,3,4] 。这个数组的元素是整数类型的。由于int 是一个可散列的类型,这个数组被成功地转换为一个集合对象。

现在,让我们看看当我们转换一个多维数组时会发生什么。

import numpy as np

arr=np.array([[1,2,3,4]])
print(set(arr))

输出

Traceback (most recent call last):
  File "C:\Users\paian\PycharmProjects\Finxter\venv\share\unhashable_type_ndarray.py", line 4, in <module>
    print(set(arr))
TypeError: unhashable type: 'numpy.ndarray'

在这种情况下,我们看到一个错误。因为 Python 解释器检查数组的元素是否是可散列的,它注意到该元素是一个ndarray 对象。一个错误显示出来,因为ndarray对象是不可哈希的。

修复。

为了解决这个错误,我们必须正确访问元素数据。在这种情况下,我们可以通过指定set(arr[0]) 来解决这个错误。

这在下面的代码片断中显示。

import numpy as np

arr=np.array([[1,2,3,4]])
print(set(arr[0]))

输出

{1, 2, 3, 4}

案例 2: 将一个 ndarray 对象指定为字典的关键字

在 Python 中,只有可散列的对象可以被添加为dictionarykey。如果你添加任何不可哈希的对象作为 dictionary key,你会看到一个错误。

请看下面的例子

import numpy as np

arr=np.array([[1],[2],[3],[4]])

a=dict()
# Adding the first element from the array as a dictionary key
a[arr[0]]= "Value"

输出

Traceback (most recent call last):
  File "C:\Users\paian\PycharmProjects\Finxter\venv\share\unhashable_type_ndarray.py", line 5, in <module>
    a[arr[0]]= "Value"
TypeError: unhashable type: 'numpy.ndarray'

我们看到一个错误,因为arr[0][1] ,它是一个 ndarray 对象 (不可哈希的类型)

修复

为了解决这个问题,正确地对内部元素进行索引,如下图所示。

import numpy as np

arr=np.array([[1],[2],[3],[4]])

a=dict()
# Adding the first element from the array as a dictionary key
a[arr[0,0]]= "Value"

print(a)

输出

{1: 'Value'}

案例3:将ndarray对象添加到一个集合中

集合对象只能包含可散列的元素。如果你添加任何不可哈希的对象类型作为集合元素,你会看到一个错误。

例子

让我们看看如果有一个数组[1,2,3,4] ,你想把这个数组的所有元素添加到一个集合中会发生什么。

import numpy as np

arr=np.array([1,2,3,4])
a=set()
a.add(arr)

输出

Traceback (most recent call last):
  File "C:\Users\...\unhashable_type_ndarray.py", line 5, in <module>
    a.add(arr)
TypeError: unhashable type: 'numpy.ndarray'

我们看到一个错误,因为我们添加了数组对象而不是它的元素在 [set.add()](https://blog.finxter.com/python-set-add/)函数中添加数组对象而不是它的元素。

修复

为了解决这个问题,添加数组的元素而不是数组对象,如下图所示。

import numpy as np

arr=np.array([1,2,3,4])
a=set()

for ele in arr:
   a.add(ele)
print(a)

输出:要解决这个问题,需要添加数组的元素,而不是数组对象,如下图所示

{1, 2, 3, 4}

结论

我们已经到了这篇文章的结尾。我希望这篇文章能提供一些信息。