在操作数组时,它们的数据有时会被复制到新数组中,有时则不会。这通常是初学者感到困惑的根源。有三种情况:
(1)No Copy at All:没有副本,简单赋值不会复制对象或其数据.
a = np.array([1,2,3,4])
b = a
a[0]=9999 # 修改a[0] ,观察b是否有变化
print(b)
print(b is a) # is比较:1.内容相同 2.内存中地址相同
print(id(b)) # id() 返回对象的唯一身份标识
print(id(a))
[9999 2 3 4] # 说明修改a,b也会跟着变
True # 说明a和b是同一对象的不同名称,它们指向同一个地址
2326315171888
2326315171888
(2)View or Shallow Copy:视图或浅层副本,不同的数组对象可以共享相同的数据,该方法创建一个查看相同数据的新数组对象。切片操作就是返回数组的视图。
例如,c = a.view()创建了一个新的对象,这两个对象共享相同的数据,a和c都可以对数组的值进行修改,但是副本c不能修改数组的形状
a = np.array([1,2,3,4]) # 创建数组a
c = a.view() # 创建视图c
a[0]=9999
c[3]=1234
print(id(a))
print(id(c))
c=c.reshape((2,2)) # 修改c的形状,观察对a的影响
print(a)
print(c)
a=a.reshape((4,1)) # 修改a的形状,观察对c的影响
print(a)
print(c)
3036131721264 #id(a)
3036428234544 #id(c) a和c的内存地址不同
[9999 2 3 1234] # a c 都可以改变数组的值
[[9999 2] # c无法改变a的形状
[ 3 1234]]
[[9999]
[ 2]
[ 3]
[1234]]
[[9999 2]
[ 3 1234]] # a也无法改变c的形状
(3)Deep Copy:深度复制/深拷贝,该方法创建数组及其数据的完整副本。
有时,如果不再需要原始数组,则应在切片后进行深度复制。例如,假设是一个巨大的中间结果,而最终结果只包含一小部分,在使用切片构造时应进行深度复制,然后可以将中间结果删掉。
a = np.array([[1,2,3,4],[5,6,7,8]])
b = a.copy()
a[0,0]=9999
print(a is b)
print(b)
False
[[1 2 3 4]
[5 6 7 8]] # a的改动对b完全没影响