如何判断NumPy是创建视图还是副本?

Hoo*_*ked 63 python numpy copy

对于最小的工作示例,让我们数字化2D数组.numpy.digitize需要一维数组:

import numpy as np
N = 200
A = np.random.random((N, N))
X = np.linspace(0, 1, 20)
print np.digitize(A.ravel(), X).reshape((N, N))
Run Code Online (Sandbox Code Playgroud)

现在文档说:

......只在需要时才制作副本.

ravel在这种情况下,如何知道副本是否"需要"?通常 - 有没有办法可以确定特定操作是创建副本还是视图?

mgi*_*son 69

这个问题是非常相似的问题,我问了一段时间后:

您可以检查base属性.

a = np.arange(50)
b = a.reshape((5, 10))
print (b.base is a)
Run Code Online (Sandbox Code Playgroud)

然而,这并不完美.您还可以检查它们是否共享内存np.may_share_memory.

print (np.may_share_memory(a, b))
Run Code Online (Sandbox Code Playgroud)

您还可以检查flags属性:

print (b.flags['OWNDATA'])  #False -- apparently this is a view
e = np.ravel(b[:, 2])
print (e.flags['OWNDATA'])  #True -- Apparently this is a new numpy object.
Run Code Online (Sandbox Code Playgroud)

但最后一个对我来说似乎有点可疑,虽然我不能完全理解为什么......

  • @amicitas,这是因为`e`实际上是`e.base`的一个视图,它本身就是`reshape`操作产生的数组的实际副本.请参见[此处](http://stackoverflow.com/q/28886731/2476444). (3认同)
  • 我只是尝试了其中一些并使用`flags ['OWNDATA']`在某些情况下肯定会失败.在你的例子中,如果你使用`e = np.reshape(b [:,2], - 1)`而不是`ravel`,`flags ['OWNDATA']`将为False,即使有副本. (2认同)
  • @mgilson第一个解决方案在哪方面不完美? (2认同)

ami*_*tas 18

重塑文档中,有一些信息表明如果无法生成视图,如何确保异常:

如果不复制数据,并不总是可以更改数组的形状.如果要在复制数据时引发错误,则应将新形状分配给数组的shape属性:

>>> a = np.zeros((10, 2))
# A transpose make the array non-contiguous
>>> b = a.T
# Taking a view makes it possible to modify the shape without modiying the
# initial object.
>>> c = b.view()
>>> c.shape = (20)
AttributeError: incompatible shape for a non-contiguous array
Run Code Online (Sandbox Code Playgroud)



这不是你问题的答案,但在某些情况下,它可能同样有用.