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


69

作为一个最小的工作示例,让我们数字化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))

现在文档说

...仅在需要时制作副本。

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


如果你要复制力,我发现最好的办法是使用np.copy,或np.array像tr = np.array(a.T, copy=True)
伊霍尔Mé

Answers:


77

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

您可以检查base属性。

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

但是,这并不完美。您也可以使用查看它们是否共享内存np.may_share_memory

print (np.may_share_memory(a, b))

您还可以检查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.

但这最后一个对我来说似乎有点可疑,尽管我不太清楚为什么...


有趣,感谢您提供答案的链接。我将保留我的问题,因为“视图”与“共享”的用语是不同的(并且没有出现在搜索中)。

@Hooked-是的,这仅够我回答您的问题,而不是将其标记为重复(我不知道其他人会怎么想)。无论如何,希望这会有所帮助。
mgilson 2012年

2
我只是尝试其中的一些,flags['OWNDATA']在某些情况下使用肯定会失败。在您的示例中,如果使用e = np.reshape(b[:, 2], -1)代替ravelflags['OWNDATA']则即使创建了副本,也将为False。
2013年

3
@amicitas,这是因为e实际上是一个视图,e.base该视图本身就是该reshape操作生成的数组的实际副本。见进一步这里
奥利弗·W·

@mgilson第一种解决方案不完美吗?
马林

20

重塑文档中,有一些有关如何确保无法创建视图的异常的信息:

在不复制数据的情况下,并非总是可以更改数组的形状。如果要在复制数据时引发错误,则应将新形状分配给数组的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



这并不完全是您问题的答案,但是在某些情况下,它可能同样有用。


我仍然对为什么这样做感到困惑。为什么我应该能够将形状应用于非视图?
Seanny123 '18 -4-6
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.