python - numpy ndarray 可哈希性

标签 python numpy

我在理解如何管理 numpy 对象的可哈希性时遇到了一些问题。

>>> import numpy as np
>>> class Vector(np.ndarray):
...     pass
>>> nparray = np.array([0.])
>>> vector = Vector(shape=(1,), buffer=nparray)
>>> ndarray = np.ndarray(shape=(1,), buffer=nparray)
>>> nparray
array([ 0.])
>>> ndarray
array([ 0.])
>>> vector
Vector([ 0.])
>>> '__hash__' in dir(nparray)
True
>>> '__hash__' in dir(ndarray)
True
>>> '__hash__' in dir(vector)
True
>>> hash(nparray)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'numpy.ndarray'
>>> hash(ndarray)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'numpy.ndarray'
>>> hash(vector)
-9223372036586049780
>>> nparray.__hash__()
269709177
>>> ndarray.__hash__()
269702147
>>> vector.__hash__()
-9223372036586049780
>>> id(nparray)
4315346832
>>> id(ndarray)
4315234352
>>> id(vector)
4299616456
>>> nparray.__hash__() == id(nparray)
False
>>> ndarray.__hash__() == id(ndarray)
False
>>> vector.__hash__() == id(vector)
False
>>> hash(vector) == vector.__hash__()
True

怎么会

  • numpy 对象定义了一个 __hash__ 方法但是不可哈希
  • 派生 numpy.ndarray 的类定义了 __hash__ 并且可散列的吗?

我错过了什么吗?

我正在使用 Python 2.7.1 和 numpy 1.6.1

感谢您的帮助!

编辑:添加对象 ids

编辑2: 在 deinonychusaur 评论之后并试图弄清楚散列是否基于内容,我玩了 numpy.nparray.dtype 并发现了一些我觉得很奇怪的东西:

>>> [Vector(shape=(1,), buffer=np.array([1], dtype=mytype), dtype=mytype) for mytype in ('float', 'int', 'float128')]
[Vector([ 1.]), Vector([1]), Vector([ 1.0], dtype=float128)]
>>> [id(Vector(shape=(1,), buffer=np.array([1], dtype=mytype), dtype=mytype)) for mytype in ('float', 'int', 'float128')]
[4317742576, 4317742576, 4317742576]
>>> [hash(Vector(shape=(1,), buffer=np.array([1], dtype=mytype), dtype=mytype)) for mytype in ('float', 'int', 'float128')]
[269858911, 269858911, 269858911]

我很困惑...在 numpy 中有一些(类型无关的)缓存机制吗?

最佳答案

我在 Python 2.6.6 和 numpy 1.3.0 中得到相同的结果。根据the Python glossary ,如果定义了 __hash__(并且不是 None),并且 __eq____cmp__ 对象应该是可散列的被定义为。 ndarray.__eq__ndarray.__hash__ 都被定义并返回一些有意义的东西,所以我不明白为什么 hash 会失败。快速谷歌后,我找到了 this post on the python.scientific.devel mailing list ,它指出数组从未被设计为可散列的——所以为什么 ndarray.__hash__ 被定义,我不知道。请注意,isinstance(nparray, collections.Hashable) 返回 True

编辑:请注意 nparray.__hash__() 返回与 id(nparray) 相同的结果,因此这只是默认实现。也许很难或不可能在早期版本的 python 中删除 __hash__ 的实现(__hash__ = None 技术显然是在 2.6 中引入的),所以他们使用了某种C API 神奇地以一种不会传播到子类的方式实现这一点,并且不会阻止您显式调用 ndarray.__hash__

Python 3.2.2 和存储库中当前的 numpy 2.0.0 有所不同。 __cmp__ 方法不再存在,因此可哈希性现在需要 __hash____eq__(参见 Python 3 glossary)。在这个版本的numpy中,定义了ndarray.__hash__,但是它只是None,所以不能被调用。 hash(nparray) 失败,isinstance(nparray, collections.Hashable) 按预期返回 Falsehash(vector) 也失败了。

关于python - numpy ndarray 可哈希性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9785514/

相关文章:

python - 重新定义 __and__ 运算符

python - 给出字典的笛卡尔积

python - 如何在 tf.estimator 的 input_fn 中使用 tf.data 的可初始化迭代器?

python - 使用 NumPy 计算向量中的值

python - 成对的 haversine 距离计算

python - 如何使用 SQLAlchemy 在表之间建立关系?

python - 装饰实例方法并从装饰器中调用它

python - numpy数组的缓冲区分区

python - 为什么 numpy std() 与 matlab std() 给出不同的结果?

python - 错误或本应是 : numpy raises "ValueError: too many boolean indices" for repeated boolean indices