如何分辨 NumPy 创建的是视图还是副本?

作为一个最简单的工作示例,让我们将一个2D 数组数字化。 numpy.digitize需要一个1D 数组:

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))

现在是 文件上说:

... 只有在需要的时候才会复制一份。

在这种情况下,我如何知道是否需要 ravel副本?一般来说,有没有一种方法可以确定一个特定的操作是创建一个副本还是一个视图?

18645 次浏览

This question is very similar to a question that I asked a while back:

You can check the base attribute.

a = np.arange(50)
b = a.reshape((5, 10))
print (b.base is a)

However, that's not perfect. You can also check to see if they share memory using np.may_share_memory.

print (np.may_share_memory(a, b))

There's also the flags attribute that you can check:

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.

But this last one seems a little fishy to me, although I can't quite put my finger on why...

In the documentation for reshape there is some information about how to ensure an exception if a view cannot be made:

It is not always possible to change the shape of an array without copying the data. If you want an error to be raised if the data is copied, you should assign the new shape to the shape attribute of the array:

>>> 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



This is not exactly an answer to your question, but in certain cases it may be just as useful.