Numpy,数组没有自己的数据?
我试着用 resize
来调整一个数组,像这样:
a = np.array([1,2,3,4,5,6], dtype=np.uint8)
a.resize(4,2)
print a
结果是好的!(我意思是没有报错)。但是当我运行这段代码:
a = np.array([1,2,3,4,5,6], dtype=np.uint8).reshape(2,3)
a.resize(4,2)
print a
却出现了一个错误,提示说 ValueError: cannot resize this array: it does not own its data
我的问题是:为什么在使用 reshape
之后,数组的“所有权”会改变?这个“所有权”是给了谁呢?因为 reshape
并没有创建新的内存,它是在同一个数组的内存上操作!那为什么“所有权”会改变呢?
我看了 np.reshape 和 ndarray.resize 的文档,但我还是不明白原因。我还看了 这篇帖子。我可以在使用 resize
方法之前,先检查 ndarray.flags
。
1 个回答
29
我们先从以下内容开始:
>>> a = np.array([1,2,3,4,5,6], dtype=np.uint8)
>>> b = a.reshape(2,3)
>>> b[0,0] = 5
>>> a
array([5, 2, 3, 4, 5, 6], dtype=uint8)
在这里我可以看到,数组 b
不是一个独立的数组,而只是数组 a
的一个视图(这就是理解“OWNDATA”标志的另一种方式)。简单来说,a
和 b
都指向内存中的同一份数据,但 b
是以不同的形状来看待 a
。调用 resize
函数,比如 ndarray.resize
,试图直接在原地改变数组的大小,但因为 b
只是 a
的视图,所以这样做是不允许的,原因在于 resize
的定义:
引用计数检查的目的是确保你不会把这个数组当作另一个 Python 对象的缓冲区,然后重新分配内存。
为了绕过这个问题,你可以从 numpy 调用 resize
(而不是作为 ndarray 的一个属性),这样它会自动检测这个问题并复制数据:
>>> np.resize(b,(4,2))
array([[5, 2],
[3, 4],
[5, 6],
[5, 2]], dtype=uint8)
编辑:正如 CT Zhu 正确提到的,np.resize
和 ndarray.resize
以两种不同的方式添加数据。为了重现 ndarray.resize
的预期行为,你需要做以下操作:
>>> c = b.copy()
>>> c.resize(4,2)
>>> c
array([[5, 2],
[3, 4],
[5, 6],
[0, 0]], dtype=uint8)