【发布时间】:2012-03-21 19:14:31
【问题描述】:
我在理解如何管理 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 中有一些(类型无关的)缓存机制吗?
【问题讨论】:
-
这似乎展示了如何让它工作,似乎处理了数组是可变的事实。 stackoverflow.com/a/5173201/1099682
-
我知道可变对象不应该是可散列的。但是在这里,我的
Vectorclass 只是从numpy.ndarray派生而来,它是不可散列的,但Vector类是,即使它是可变的。 -
在我看来,散列的是内存参考或其他东西,如果你只是重复 vector = Vector(shape=(1,), buffer=nparray) 并检查它应该有的散列改变了。