Python numpy ndarray的子类不';I don’我没有按预期工作
`各位好 我发现对ndarray进行子类化时有一种奇怪的行为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
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