Numpy教程

NumPy 数组副本和视图

NumPy 数组副本和视图的操作实例
副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。
视图是数据的一个别称或引用,通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。

副本和视图之间的区别

副本和数组视图之间的主要区别在于副本是一个新数组,而这个视图只是原始数组的视图。 副本拥有数据,对副本所做的任何更改都不会影响原始数组,对原始数组所做的任何更改也不会影响副本。 视图不拥有数据,对视图所做的任何更改都会影响原始数组,而对原始数组所做的任何更改都会影响视图。
视图一般发生在:
1、numpy 的切片操作返回原数据的视图。 2、调用 ndarray 的 view() 函数产生一个视图。
副本一般发生在:
Python 序列的切片操作,调用deepCopy()函数。 调用 ndarray 的 copy() 函数产生一个副本。

无复制

简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同id()来访问它。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。此外,一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。
>>> import numpy as np
>>> a = np.arange(6)
>>> print ('我们的数组是:',a)
我们的数组是: [0 1 2 3 4 5]
>>> print ('调用 id() 函数:',id(a))
调用 id() 函数: 4553321728
>>> b = a
>>> print (b)
[0 1 2 3 4 5]
>>> print ('b 拥有相同 id():',id(b))
b 拥有相同 id(): 4553321728
>>> b.shape = 3,2
>>> print (b)
[[0 1]
 [2 3]
 [4 5]]
>>> print (a)
[[0 1]
 [2 3]
 [4 5]]
>>>

视图或浅拷贝

ndarray.view() 方会创建一个新的数组对象,该方法创建的新数组的维数更改不会更改原始数据的维数。
import numpy as np
 
# 最开始 a 是个 3X2 的数组
a = np.arange(6).reshape(3,2)
print ('数组 a:')
print (a)
print ('创建 a 的视图:')
b = a.view()
print (b)
print ('两个数组的 id() 不同:')
print ('a 的 id():')
print (id(a))
print ('b 的 id():' )
print (id(b))
# 修改 b 的形状,并不会修改 a
b.shape = 2,3
print ('b 的形状:')
print (b)
print ('a 的形状:')
print (a)
输出结果为:
数组 a:
[[0 1]
 [2 3]
 [4 5]]
创建 a 的视图:
[[0 1]
 [2 3]
 [4 5]]
两个数组的 id() 不同:
a 的 id():
4314786992
b 的 id():
4315171296
b 的形状:
[[0 1 2]
 [3 4 5]]
a 的形状:
[[0 1]
 [2 3]
 [4 5]]
使用切片创建视图修改数据会影响到原始数组:
import numpy as np
arr = np.arange(12)
print ('我们的数组:')
print (arr)
print ('创建切片:')
a=arr[2:]
b=arr[2:]
a[1]=123456
b[2]=23445
print(arr)
print(id(a),id(b),id(arr[3:]))
输出结果为:
我们的数组:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
创建切片:
[ 0 1 2 123456 23445 5 6 7 8 9
     10 11]
4669930672 4444330304 4670012352
Process finished with exit code 0
变量 a,b 都是 arr 的一部分视图,对视图的修改会直接反映到原数据中。但是我们观察 a,b 的 id,他们是不同的,也就是说,视图虽然指向原数据,但是他们和赋值引用还是有区别的。

副本或深拷贝

ndarray.copy() 函数创建一个副本。 对副本数据进行修改,不会影响到原始数据,它们物理内存不在同一位置。
import numpy as np
 
a = np.array([[10,10], [2,3], [4,5]])
print ('数组 a:')
print (a)
print ('创建 a 的深层副本:')
b = a.copy()
print ('数组 b:')
print (b)
# b 与 a 不共享任何内容
print ('我们能够写入 b 来写入 a 吗?')
print (b is a)
print ('修改 b 的内容:')
b[0,0] = 100
print ('修改后的数组 b:')
print (b)
print ('a 保持不变:')
print (a)
输出结果为:
数组 a:
[[10 10]
 [ 2 3]
 [ 4 5]]
创建 a 的深层副本:
数组 b:
[[10 10]
 [ 2 3]
 [ 4 5]]
我们能够写入 b 来写入 a 吗?
False
修改 b 的内容:
修改后的数组 b:
[[100 10]
 [ 2 3]
 [ 4 5]]
a 保持不变:
[[10 10]
 [ 2 3]
 [ 4 5]]
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4