【问题标题】:Numpy functions return array class instance when called on subclass of ndarrayNumpy 函数在 ndarray 的子类上调用时返回数组类实例
【发布时间】:2016-09-13 13:00:05
【问题描述】:

一些 numpy 函数(逻辑上)返回标量:

>>> my_arr = np.ndarray(shape=(1,))
>>> type(np.max(my_arr))
<type 'numpy.float64'>

但仅在使用 ndarray 而不是子类调用时:

>>> class CustomArray(np.ndarray):
...     pass
>>> my_arr = CustomArray(shape=(1,))
>>> type(np.max(my_arr))
<class '__main__.CustomArray'>

这是为什么?我希望两者都返回一个标量(&lt;type 'numpy.float64'&gt; 类型,或者前者返回一个np.ndarray 实例,后者返回一个CustomArray 实例。但是相反,我得到了这两种行为的组合。我可以通过改变我自己的班级来改变这种行为?

我在讨论子类化 ndarray (http://docs.scipy.org/doc/numpy-1.9.2/user/basics.subclassing.html) 的文档页面上没有看到任何可以解释这一点的内容。

(运行 Python 2.7.10,numpy 1.9.2,以防万一。)

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    这是因为max() 没有在CustomArray 中重载。如果您尝试一下,my_array.max() 返回一个 CustomArray 对象而不是标量。

    my_array = CustomArray(shape=(1,))
    print my_array.max()
    >> CustomArray(9.223372036854776e+18)
    

    np.max 内部调用np.amax,最终调用np.maximum.reduce。这是 map-reduce 的标准 reduce,并返回 max 返回的基础对象。因此,np.max 返回的类型实际上是对象上调用的max() 方法返回的类型。您可以将其覆盖为:

    class CustomArray(np.ndarray):
       def max(self, axis, out):
          return np.ndarray(self.shape, buffer=self).max(axis, out)
    
    type(np.max(my_arr))
    >> numpy.float64
    

    诀窍是将 self 向上转换为 np.ndarray 并使用它找到最大值。

    【讨论】:

    • 我猜我必须更改ndarray 实例获得的几乎所有方法? (我只是以max 为例。)
    • 此外,如果子类实际上没有改变任何行为,这并不能回答为什么子类的实例与 ndarray 的实例行为不同的问题。
    • 是的,如果您想要正确的返回类型,您可能必须更新每个相关的方法。类主体不会更新任何内容,但 max() 的默认覆盖(以及 sum() 等其他方法)与基本 np.ndarray 不同。
    • 为什么它们不同呢? ndarray.max 中是否有明确的检查以检查 self 实际上是 ndarray 的实例而不是子类或其他什么?
    • 查看np.matrixmasked 的代码,看看他们是如何处理这个问题的。
    猜你喜欢
    • 2011-09-05
    • 2016-11-03
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多