带副本的 Numpy 数组赋值

Posted

技术标签:

【中文标题】带副本的 Numpy 数组赋值【英文标题】:Numpy array assignment with copy 【发布时间】:2013-11-09 16:32:32 【问题描述】:

例如,如果我们有一个numpy 数组A,并且我们想要一个具有相同元素的numpy 数组B

以下(见下文)方法有什么区别?什么时候分配额外的内存,什么时候不分配?

    B = A B[:] = A(与B[:]=A[:]相同?) numpy.copy(B, A)

【问题讨论】:

【参考方案1】:

所有三个版本都做不同的事情:

    B = A

    这会将新名称 B 绑定到已命名为 A 的现有对象。之后它们引用同一个对象,因此如果您在原地修改一个对象,您也会通过另一个对象看到更改。

    B[:] = A(与B[:]=A[:]相同?)

    这会将A 中的值复制到现有数组B 中。这两个数组必须具有相同的形状才能工作。 B[:] = A[:] 做同样的事情(但B = A[:] 会做更像 1 的事情)。

    numpy.copy(B, A)

    这不是合法的语法。你的意思可能是B = numpy.copy(A)。这与 2 几乎相同,但它创建了一个新数组,而不是重用 B 数组。如果没有其他引用之前的B 值,最终结果将与 2 相同,但在复制过程中会暂时使用更多内存。

    或者你的意思是numpy.copyto(B, A),这是合法的,相当于2?

【讨论】:

@Mr_and_Mrs_D:Numpy 数组的工作方式与列表不同。切片数组不会产生副本,它只是在现有数组的数据上创建一个新视图。 but B = A[:] would do something more like 1 是什么意思?据此***.com/a/2612815new_list = old_list[:]也是副本。 @mrgloom:在切片和复制其内容时,Numpy 数组的工作方式与列表不同。数组是存储数值的底层内存块的“视图”。像some_array[:] 这样的切片将创建一个新的数组对象,但该新对象将是与原始数组相同内存的视图,不会被复制。这就是为什么我说它更像B = A。它只需要O(1) 空间和时间,而不是真正副本所需的O(n) 根据文档,首选的“复制”方法是B = A.copy()。但是此表单默认不保留顺序,您需要B = A.copy(order='k')【参考方案2】:
    B=A 创建引用 B[:]=A 复制一份 numpy.copy(B,A) 复制一份

最后两个需要额外的内存。

要进行深层复制,您需要使用B = copy.deepcopy(A)

【讨论】:

参考您的第二个示例:B[:] = A 是否 制作对象类型数组的深层副本,例如A = np.array([[1,2,3],[4,5]]); B = np.array([None,None], dtype='O')。现在试试B[:] = A; B[0][0]=99,这将改变A 和B 中的第一个元素!据我所知,除了copy.deepcopy【参考方案3】:

这对我来说是唯一可行的答案:

B=numpy.array(A)

【讨论】:

以上是关于带副本的 Numpy 数组赋值的主要内容,如果未能解决你的问题,请参考以下文章

Numpy常用概念-对象的副本和视图向量化广播机制

关于 python 何时自动创建数组副本的文档

Numpy 数组和列表的多重赋值,一个奇怪的例子

处理numpy数组时赋值运算符中的指针行为?

初始化多个 Numpy 数组(多重赋值) - 像 MATLAB deal()

带数组的重载赋值运算符