在我的previous question中,我学会了适当地调整子类ndarray
的大小。整洁。不幸的是,当我要调整大小的数组是计算的结果时,这种方法不再有效:
import numpy as np
class Foo(np.ndarray):
def __new__(cls,shape,dtype=np.float32,buffer=None,offset=0,
strides=None,order=None):
return np.ndarray.__new__(cls,shape,dtype,buffer,offset,strides,order)
def __array_prepare__(self,output,context):
print output.flags['OWNDATA'],"PREPARE",type(output)
return np.ndarray.__array_prepare__(self,output,context)
def __array_wrap__(self,output,context=None):
print output.flags['OWNDATA'],"WRAP",type(output)
return np.ndarray.__array_wrap__(self,output,context)
a = Foo((32,))
#resizing a is no problem
a.resize((24,),refcheck=False)
b = Foo((32,))
c = Foo((32,))
d = b+c
#Cannot resize `d`
d.resize((24,),refcheck=False)
准确的输出(包括回溯)是:
^{pr2}$我认为这是因为numpy
创建了一个新的ndarray
,并将其传递给__array_prepare__
。但在某个时候,似乎“output
”
array得到view-casted to my ^{
有没有什么方法,通过某种新巫术(__array_prepare__
,__array__
)等,将数据的所有权转移到我的子类实例中?在
怎么样:
它似乎成功地调整了大小(并减少了内存消耗):
^{pr2}$收益率
这不是一个令人满意的答案,但它也不适合评论。。。您可以使用ufunc的
out
参数来解决数据的拥有问题。一个愚蠢的例子:我认为上面的输出与
c[:] = a + b
获得数据的所有权是一致的,但代价是将数据从临时数组复制到c
。但是在使用out
参数时,不应该发生这种情况。由于您已经担心数学表达式中的中间存储,所以对如何处理它进行微管理可能不是一件坏事。也就是说,更换
^{pr2}$与
你可以保存一些你自己的数据。它确实把“可读性很重要”的咒语抛到了窗外,但是。。。
是的,
ndarray.__array_prepare__
调用output.view
,这将返回一个不拥有其数据的数组。我做了一点实验,但找不到一个简单的方法。
虽然我同意这种行为并不理想,但至少在您的用例中,我认为
d
不拥有其数据是可以接受的。Numpy广泛使用视图,如果您坚持在使用Numpy数组时避免创建任何视图,那么您的生活将非常艰难。我还认为,根据我的经验,
resize
一般应该避免。如果避免使用resize
,那么使用创建的视图应该不会有任何问题。它有一种骇人听闻的感觉,而且很难使用它(正如您可能开始理解的那样,在使用它时遇到了两个经典错误之一:it does not own its data
。另一个是cannot resize an array that has been referenced
)。(另一个问题在quesion中描述。)由于您使用
resize
的决定来自于对另一个问题的回答,所以我将把剩下的答案there张贴出来。相关问题 更多 >
编程相关推荐