Numpy,数组没有自己的数据?

30 投票
1 回答
40539 浏览
提问于 2025-04-18 03:59

我试着用 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.reshapendarray.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”标志的另一种方式)。简单来说,ab 都指向内存中的同一份数据,但 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.resizendarray.resize 以两种不同的方式添加数据。为了重现 ndarray.resize 的预期行为,你需要做以下操作:

>>> c = b.copy()
>>> c.resize(4,2)
>>> c
array([[5, 2],
       [3, 4],
       [5, 6],
       [0, 0]], dtype=uint8)

撰写回答