单个索引进入numpy结构化数组子类

时间:2013-11-18 19:35:59

标签: python numpy

我正在尝试子类化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

2 个答案:

答案 0 :(得分:1)

尝试:

print 'type(obj[[0]]):  ',type(obj[[0]])   # Why numpy.void???
print 'obj[[0]].bar(): ',obj[[0]].bar()  

您正在看到使用标量索引和列表(数组)访问之间的区别。

来自记录数组的用户指南

  

这里我们创建了一个长度为2的一维数组。这个数组的每个元素都是一个包含三个项目的记录,一个32位整数,一个32位浮点数和一个长度为10或更小的字符串。如果我们在第二个位置索引这个数组,我们得到第二个记录:

obj[0]返回一条记录,而不是任何数组。 obj[[0]]返回一个包含一条记录的数组。

同样,x=np.array([0,1,2,3]); type(x[0])不是数组;它是一个标量(dtype)。

答案 1 :(得分:1)

错误与超类无关,它来自视图和自定义dtype:

>>> arr = np.arange((3+2)*2,dtype=np.float64).view(dtype=np.dtype([('BAR',np.float64,3),('other',np.float64,2)]))
>>> arr[0]
([0.0, 1.0, 2.0], [3.0, 4.0])
>>> type(arr[0])
<type 'numpy.void'>