【问题标题】:Single index into numpy structured array subclassnumpy结构化数组子类的单个索引
【发布时间】: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

【问题讨论】:

    标签: python numpy


    【解决方案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'>
    

    【讨论】:

    • 这就是我所说的“(实际上,无论是否子类化,从结构化数组中检索单个索引都会返回一个 numpy.void 类型的对象。)”但是,我的上下文是子类化,并且我想知道如何最好地更改我的代码以提供一个维护 Foo 接口的对象。
    【解决方案2】:

    试试:

    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)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      • 2014-11-10
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      相关资源
      最近更新 更多