【发布时间】:2013-11-19 04:57:35
【问题描述】:
我正在尝试对一个 numpy 结构化数组进行子类化,以便可以向子类添加特殊方法。一切正常,直到我从数组中检索到单个索引。发生这种情况时,将返回类型为 numpy.void 的对象,而不是子类的类型。 (实际上,无论是否子类化,从结构化数组中检索单个索引都会返回一个 numpy.void 类型的对象。)这是为什么?以及如何确保返回我的类的实例?我认为覆盖 __getitem__ 将是可行的方法,但我对 ndarray 子类化还不够熟悉,因此我确信我不会搞砸其他事情。请指教。
这是我所描述的行为示例:
import numpy as np
# The ndarray subclass
class Foo(np.ndarray):
# Do something special that uses a field of the structured array
def bar(self):
return self['BAR']
def main():
# Set up the structured array
arr = np.arange((3+2)*2,dtype=np.float64).view(dtype=np.dtype([('BAR',np.float64,3),('other',np.float64,2)]))
# Get a Foo instance using the data
obj = arr.view(Foo)
print 'type(obj): ',type(obj) # As expected: Foo object
print 'type(obj[:1]): ',type(obj[:1]) # As expected: Foo object
print 'type(obj[0]): ',type(obj[0]) # Why numpy.void???
print 'obj.bar():' # As expected
print obj.bar() # As expected
print 'obj[:1].bar():',obj[:1].bar() # As expected
print 'obj[0].bar(): ',obj[0].bar() # Causes exception: AttributeError: 'numpy.void' object has no attribute 'bar'
if __name__=="__main__":
main()
输出如下:
type(obj): <class '__main__.Foo'>
type(obj[:1]): <class '__main__.Foo'>
type(obj[0]): <type 'numpy.void'>
obj.bar():
[[ 0. 1. 2.]
[ 5. 6. 7.]]
obj[:1].bar(): [[ 0. 1. 2.]]
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/ipdb/__main__.py", line 138, in main
pdb._runscript(mainpyfile)
File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/pdb.py", line 1233, in _runscript
self.run(statement)
File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/bdb.py", line 387, in run
exec cmd in globals, locals
File "", line 1, in
File "scratch.py", line 1, in
import numpy as np
File "scratch.py", line 25, in main
print 'obj[0].bar(): ',obj[0].bar() # Causes exception: AttributeError: 'numpy.void' object has no attribute 'bar'
AttributeError: 'numpy.void' object has no attribute 'bar'
obj[0].bar(): Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
【问题讨论】: