简而言之:您不能总是依靠
ndarray.flags['OWNDATA']。
>>> import numpy as np>>> x = np.random.rand(2,2)>>> y = x.T>>> q = y.reshape(4)>>> y[0,0]0.86751629121019136>>> y[0,0] = 1>>> qarray([ 0.86751629, 0.87671107, 0.65239976, 0.41761267])>>> xarray([[ 1. , 0.65239976], [ 0.87671107, 0.41761267]])>>> yarray([[ 1. , 0.87671107], [ 0.65239976, 0.41761267]])>>> y.flags['OWNDATA']False>>> x.flags['OWNDATA']True>>> q.flags['OWNDATA']False>>> np.may_share_memory(x,y)True>>> np.may_share_memory(x,q)False
由于
q未反映第一个元素(例如
x或)中的更改
y,因此它必须以某种方式成为数据的所有者(在下面以某种方式进行解释)。
OWNDATA在numpy-discussion
邮件列表中有更多关于该标志的讨论。在如何判断NumPy是创建视图还是副本?问题,正如您所提到的,简要地提到,仅检查
flags.owndata一个
ndarray有时似乎失败并且似乎不可靠。这是因为每个
ndarray还具有一个
base属性:
如果内存起源于其他地方,则ndarray的基础是对另一个数组的引用(否则,基础是
None)。操作
y.reshape(4)创建一个副本,而不是一个视图,因为进步
y是
(8,16)。若要将其重塑为(C连续)为
(4,),内存指针将必须跳转
0->16->8->24,这不能单步执行。因此
q.base指向由强制复制操作生成的存储位置,该存储位置
y.reshape与形状相同
y,但是复制了元素,因此再次具有正常的跨度:
(16,8)。
q.base因此,它不受任何其他名称的约束,因为它是强制复制操作的结果
y.reshape(4)。只有现在才能
q.base在
(4,)形状,因为跨步允许这样做。
q那么确实是对…的看法
q.base。
对于大多数人来说将是混乱一看就知道
q.flags.owndata是
False因为,如上图所示,它不是一个视图
y。但是,它是的副本的视图
y。但是,该副本
q.base是数据的所有者。因此,如果您仔细检查,这些标志实际上是正确的。



