NumPy - 副本和视图
在执行函数时,其中一些返回输入数组的副本,而另一些返回视图。 当内容物理存储在另一个位置时,称为副本。 另一方面,如果提供了相同内存内容的对象,我们将其称为视图。副本和视图不一定都会导致内容的修改,但是当两个对象指向相同的引用时,修改其中任何一个对象,都会引起另一个对象的同步变化。
无复制
简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同id()
来访问它。id()
返回 Python 对象的通用标识符,类似于 C 中的指针。
此外,一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。
示例
import numpy as np
a = np.arange(6)
print( '我们的数组是:')
print( a)
print( '调用 id() 函数:')
print( id(a))
print( 'a 赋值给 b:')
b = a
print( b)
print( 'b 拥有相同 id():')
print( id(b))
print( '修改 b 的形状:')
b.shape = 3,2
print( b)
print( 'a 的形状也修改了:' )
print( a)
输出如下:
我们的数组是:
[0 1 2 3 4 5]
调用 id() 函数:
139747815479536
a 赋值给 b:
[0 1 2 3 4 5]
b 拥有相同 id():
139747815479536
修改 b 的形状:
[[0 1]
[2 3]
[4 5]]
a 的形状也修改了:
[[0 1]
[2 3]
[4 5]]
视图或浅复制
NumPy 拥有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)
b[0,0]=90
print(a[0,0])
输出如下:
数组 a:
[[0 1]
[2 3]
[4 5]]
创建 a 的视图:
[[0 1]
[2 3]
[4 5]]
两个数组的 id() 不同:
a 的 id():
4447675056
b 的 id():
4429253248
b 的形状:
[[0 1 2]
[3 4 5]]
a 的形状:
[[0 1]
[2 3]
[4 5]]
90
数组的切片也会创建视图:
示例
import numpy as np
a = np.array([[10,10], [2,3], [4,5]])
print( '我们的数组:')
print( a)
print( '创建切片:')
s = a[:, :2]
print( s)
输出如下:
我们的数组:
[[10 10]
[ 2 3]
[ 4 5]]
创建切片:
[[10 10]
[ 2 3]
[ 4 5]]
深复制
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]]