在操作数组的时候返回的不是视图就是副本。
副本:复制
视图:链接
副本是一个数据的完整拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。
视图是数据的一个别称或引用,通过该别称或引用亦可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。
视图一般发生在:
- 1、numpy 的切片操作返回原数据的视图。
- 2、调用 ndarray 的 view() 函数产生一个视图。
副本一般发生在:
- Python 序列的切片操作,调用deepCopy()函数。
- 调用 ndarray 的 copy() 函数产生一个副本。
赋值
赋值操作,两个变量a, b都指向同一个内存地址, b与原始数组a的id()相同。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。
一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。
import numpy as np a = np.arange(6) b = a print(‘数组a:‘,a) print(‘数组b:‘,b) print(‘a 调用 id() 函数:‘,id(a)) print(‘b 调用 id() 函数:‘,id(b)) b.shape = 3, 2 print(‘修改 b 的形状:‘) print(b) print(‘a 的形状也修改了:‘) print(a)
输出结果为:
数组a: [0 1 2 3 4 5]
数组b: [0 1 2 3 4 5]
a 调用 id() 函数: 2026424909056
b 调用 id() 函数: 2026424909056
修改 b 的形状:
[[0 1]
[2 3]
[4 5]]
a 的形状也修改了:
[[0 1]
[2 3]
[4 5]]
视图或浅拷贝
Numpy的切片操作会返回原数据的视图,切片产生的视图是原视图的一部分视图,对视图的修改会直接反映到原数据中,但它们的id是不同的。也就是说,视图虽然指向原数据,但是他们和赋值引用还是有区别的。
ndarray.view() 方会创建一个新的数组对象,该方法创建的新数组的维数更改不会更改原始数据的维数。
import numpy as np # 最开始 a 是个 3X2 的数组 a = np.arange(6).reshape(3, 2) print(‘数组 a:‘) print(a) print(‘ ‘) b = a.view() print(‘创建 a 的视图b:‘) print(b) print(‘ ‘) print(‘a 的 id():‘,id(a)) print(‘b 的 id():‘,id(b)) print(‘ ‘) # 修改 b 的形状,并不会修改 a b.shape = 2, 3 print(‘修改形状后的b:‘) print(b) print(‘ ‘) print(‘修改b形状后的a:‘) print(a)
输出结果为:
数组 a:
[[0 1]
[2 3]
[4 5]]
创建 a 的视图b:
[[0 1]
[2 3]
[4 5]]
a 的 id(): 1601808711552
b 的 id(): 1601809504256
修改形状后的b:
[[0 1 2]
[3 4 5]]
修改b形状后的a:
[[0 1]
[2 3]
[4 5]]
使用切片创建视图修改数据会影响到原始数组:
import numpy as np arr = np.arange(12) print(‘我们的数组:‘,arr) print(‘ ‘) a = arr[3:] b = arr[3:] print(‘切片a:‘,a) print(‘切片b:‘,b) print(‘ ‘) a[1] = 123 b[2] = 234 print(‘修改后的数组arr:‘) print(arr) print(‘修改后的数组a:‘) print(a) print(‘修改后的数组b:‘) print(b) print(‘ ‘) print(‘a的id:‘,id(a)) print(‘b的id:‘,id(b)) print(‘arr的id:‘,id(arr))
输出结果为:
我们的数组: [ 0 1 2 3 4 5 6 7 8 9 10 11]
切片a: [ 3 4 5 6 7 8 9 10 11]
切片b: [ 3 4 5 6 7 8 9 10 11]
修改后的数组arr:
[ 0 1 2 3 123 234 6 7 8 9 10 11]
修改后的数组a:
[ 3 123 234 6 7 8 9 10 11]
修改后的数组b:
[ 3 123 234 6 7 8 9 10 11]
a的id: 1173376024448
b的id: 1173376023968
arr的id: 1173376023888
变量 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(‘ ‘) b = a.copy() print(‘创建 a 的副本数组 b:‘) print(b) print(‘ ‘) # b 与 a 不共享任何内容 print(‘我们能够写入 b 来写入 a 吗?‘) print(b is a) print(‘ ‘) b[0, 0] = 100 print(‘修改副本b:‘) print(b) print(‘ ‘) print(‘修改副本b后,a数组不变:‘) print(a)
输出结果为:
数组 a:
[[10 10]
[ 2 3]
[ 4 5]]
创建 a 的副本数组 b:
[[10 10]
[ 2 3]
[ 4 5]]
我们能够写入 b 来写入 a 吗?
False
修改副本b:
[[100 10]
[ 2 3]
[ 4 5]]
修改副本b后,a数组:
[[10 10]
[ 2 3]
[ 4 5]]