np.copy到底是深拷贝还是浅拷贝
最近在用numpy的拷贝操作,发现网上对np.copy()究竟是深拷贝还是浅拷贝说法不一致,因此记录一下。
总结 :如果numpy array是一个简单的数组,np.copy()是深拷贝。如果numpy array内包含了对象,np.copy()是浅拷贝。
ps : arr.copy
= np.copy(arr)
实验
1. 拷贝矩阵
原始矩阵m
,分别用两种不同的方式拷贝。用np.copy()得到n
, 用浅拷贝得到z
:
python
import numpy as np
m = np.array([[0,1,2],[1,2,3],[3,4,5]])
# numpy拷贝, 等同于n = np.copy(m)
n = m.copy()
# 浅拷贝
z = m
输出:
python
>>> m
array([[0, 1, 2],
[1, 2, 3],
[3, 4, 5]])
>>> n
array([[0, 1, 2],
[1, 2, 3],
[3, 4, 5]])
>>> z
array([[0, 1, 2],
[1, 2, 3],
[3, 4, 5]])
2. 修改m的值
python
m[0][0]=-1
修改m
的值后,使用np.copy的n
值没有改变,浅拷贝z
的值发生了改变
python
>>> m
array([[-1, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
>>> n
array([[0, 1, 2],
[1, 2, 3],
[3, 4, 5]])
>>> z
array([[-1, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
3. 修改拷贝矩阵的值
修改n
的值,m
和z
值都没有改变
python
n[0][0]=-2
>>> m
array([[-1, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
>>> n
array([[-2, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
>>> z
array([[-1, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
修改z
的值,m
值改变和n
值不变
python
z[0][0]=-3
array([[-3, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
>>> n
array([[-2, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
>>> z
array([[-3, 1, 2],
[ 1, 2, 3],
[ 3, 4, 5]])
因此np.copy从以上的例子来看是深拷贝, =
是浅拷贝
官方文档
但是在 numpy官方文档中明确提到np.copy是浅拷贝。原因是如果array里的元素是一个对象时,如果对象的元素改变,原来的array的对象也会改变。也就是说numpy array中对象元素的拷贝是浅拷贝。
Note that np.copy is a shallow copy and will not copy object elements within arrays. This is mainly important for arrays containing Python objects. The new array will contain the same object which may lead to surprises if that object can be modified (is mutable):
a = np.array([1, 'm', [2, 3, 4]], dtype=object)
b = np.copy(a)
b[2][0] = 10
a
array([1, 'm', list([10, 3, 4])], dtype=object)
To ensure all elements within an object array are copied, use copy.deepcopy:
import copy
a = np.array([1, 'm', [2, 3, 4]], dtype=object)
c = copy.deepcopy(a)
c[2][0] = 10
c
array([1, 'm', list([10, 3, 4])], dtype=object)
a
array([1, 'm', list([2, 3, 4])], dtype=object)