Python numpy ndarray的子类不';I don’我没有按预期工作

Python numpy ndarray的子类不';I don’我没有按预期工作,python,numpy,Python,Numpy,`各位好 我发现对ndarray进行子类化时有一种奇怪的行为 import numpy as np class fooarray(np.ndarray): def __new__(cls, input_array, *args, **kwargs): obj = np.asarray(input_array).view(cls) return obj def __init__(self, *args, **kwargs): re

`各位好

我发现对ndarray进行子类化时有一种奇怪的行为

import numpy as np

class fooarray(np.ndarray):
    def __new__(cls, input_array, *args, **kwargs):
        obj = np.asarray(input_array).view(cls)
        return obj

    def __init__(self, *args, **kwargs):
        return

    def __array_finalize__(self, obj):
        return

a=fooarray(np.random.randn(3,5))
b=np.random.randn(3,5)

a_sum=np.sum(a,axis=0,keepdims=True)
b_sum=np.sum(b,axis=0, keepdims=True)

print a_sum.ndim #1
print b_sum.ndim #2

如您所见,
keepdims
参数不适用于我的子类
fooarray
。它失去了一个轴心。我怎样才能避免这个问题?或者更一般地说,我如何才能正确地将numpy ndarray子类化?

如果您查看相关的 作为numpy源代码的一部分,原因很清楚
a.sum(…,keepdims=True)
有效,而
np.sum(a,…,keepdims=True)
没有:

由于您已经对
np.ndarray
进行了子类化,
type(a)
fooarray
,而不是
mu.ndarray
,因此您将在此行结束:

# NOTE: Dropping the keepdims parameters here...
return sum(axis=axis, dtype=dtype, out=out)

keepdims
关键字参数是
ndarrays
的一个相对较新的功能,目前还没有为某些其他类似数组的类实现,例如
np.matrix
np.ma.masked_array
,它们也有一个
.sum()
方法,因此,对于非ndarrays,该参数当前会被删除。

np.sum
可以接受多种对象作为输入:例如,不仅是ndarray,还包括列表、生成器、
np.matrix
s。
keepdims
参数显然对列表或生成器没有意义。它也不适用于
np.matrix
实例,因为
np.matrix
s总是有两个维度。如果查看
np.matrix.sum
的调用签名,您会发现其
sum
方法没有
keepdims
参数:

Definition: np.matrix.sum(self, axis=None, dtype=None, out=None)
因此,
ndarray
的一些子类可能有
sum
方法,这些方法没有
keepdims
参数。这是一种不幸的违反,也是您遇到的陷阱的根源

现在,如果你看一下,你会发现它是一个委托函数,它试图根据第一个参数的类型来决定做什么

如果第一个参数的类型不是
ndarray
,它将删除
keepdims
参数。这样做是因为将keepdims参数传递给
np.matrix.sum
会引发异常

因此,由于
np.sum
试图以最一般的方式进行委托,而不是对ndarray的子类可能采用的参数进行任何假设,因此当传递
fooarray
时,它会删除
keepdims
参数

解决方法是不要使用
np.sum
,而是调用
a.sum
。这更直接,因为
np.sum
仅仅是一个委托函数

import numpy as np


class fooarray(np.ndarray):
    def __new__(cls, input_array, *args, **kwargs):
        obj = np.asarray(input_array, *args, **kwargs).view(cls)
        return obj

a = fooarray(np.random.randn(3, 5))
b = np.random.randn(3, 5)

a_sum = a.sum(axis=0, keepdims=True)
b_sum = np.sum(b, axis=0, keepdims=True)

print(a_sum.ndim)  # 2
print(b_sum.ndim)  # 2

一个可能的解决办法是使用
a.sum
。完全回答我的问题。谢谢你
import numpy as np


class fooarray(np.ndarray):
    def __new__(cls, input_array, *args, **kwargs):
        obj = np.asarray(input_array, *args, **kwargs).view(cls)
        return obj

a = fooarray(np.random.randn(3, 5))
b = np.random.randn(3, 5)

a_sum = a.sum(axis=0, keepdims=True)
b_sum = np.sum(b, axis=0, keepdims=True)

print(a_sum.ndim)  # 2
print(b_sum.ndim)  # 2