numpy - “np.copy是浅复制,不会复制数组中的对象元素”的解释

3

背景

请注意,np.copy是浅复制,不会复制数组内的对象元素。 这对于包含Python对象的数组尤其重要。新数组将包含同一对象,如果该对象可以被修改(可变),则可能会导致意外结果:

基于3.2 内存布局,我认为数组 a 将指向包含64位浮点数的内存区域。

换句话说,数组通常是一个连续的内存块,其部分可以使用索引方案访问。

enter image description here

因为文档中写道np.copy是浅拷贝,不会拷贝数组内的对象元素,我认为内存区域不会被复制,而是被引用。
然而,复制并不是对原始数组的视图,内存区域/地址是不同的,因为在x[0]=10之后,x[0]==z[0]是False。
x = np.array([1, 2, 3])
z = np.copy(x)
print(f"x.base {x.base} z.base {z.base}")
---
x.base None z.base None

x[0] = 10
print(x[0] == z[0])
---
False

print(f"x.base {x.base} z.base {z.base}")
---
x.base None z.base None

问题

np.copy(a) 实际上复制了什么?

如果这是一个 浅拷贝,为什么会为 z[0] 分配一个不同的内存区域?它实际上是在复制数组 x 的对象,应该称为 深拷贝 吗?还是 写时复制 呢?

或者 浅拷贝 是指,“当 np 数组的一个元素是可变容器(如列表)时,np.copy 将不会深度复制容器的内容”?

请帮助理解 z = np.copy(x) 到底做了什么以及当对 z 进行赋值操作时会发生什么。


1
你没有一个 object 类型的数组,所以不用担心 deepcopy - hpaulj
1
如果dtype是对象,数组的数据缓冲区包含对内存中其他位置的对象的引用。copy将具有一个新的数据缓冲区,但值将引用相同的对象。这与嵌套列表的浅拷贝问题相同。但是对于数值dtype,拥有一个新的数据缓冲区就足够了。新的缓冲区具有新的值。这是常规的数组拷贝,不需要过多考虑。 - hpaulj
1个回答

3
在Python中,copy.copy()方法执行浅拷贝,即仅复制原始数据类型(例如intfloat等)的对象,但组成对象(例如字典)不会被复制,而是通过指针引用。
另一方面,copy.deepcopy()方法将复制所有内容(包括诸如字典之类的复合数据结构),并将导致与第一个完全相同的新对象。
numpy模块的情况下,如果您像应该那样使用它进行数值计算(即计算数值dtypes之一的数据),则copy将等同于deepcopy(因为numpy的所有数字项都是基本的dtypes),并将导致为已复制的项分配新的数据空间。
干杯。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接