English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

NumPy 数组副本和视图

Une copie est une copie complète des données, si nous modifions la copie, cela ne touchera pas les données originales, et la mémoire physique n'est pas à la même position.
Une vue est un alias ou une référence aux données, à travers lequel on peut accéder et manipuler les données originales, mais les données originales ne produisent pas de copie. Si nous modifions la vue, cela affectera les données originales, et la mémoire physique est à la même position.

La différence entre les copies et les vues

La principale différence entre les copies et les vues des arrays est que la copie est un nouvel array, tandis que cette vue est simplement une vue de l'array original.Les copies possèdent des données, toute modification apportée à la copie ne touchera pas l'array original, et toute modification apportée à l'array original ne touchera pas la copie.Les vues ne possèdent pas de données, toute modification apportée à la vue affectera l'array original, et toute modification apportée à l'array original affectera la vue.

Les vues se produisent généralement :

1、Les opérations de tranchage de numpy retournent une vue des données originales.2、Créer une vue en utilisant la fonction view() de ndarray.

Les copies se produisent généralement :

Opérations de tranchage des séquences Python, appeler la fonction deepCopy().Créer une copie en utilisant la fonction copy() de ndarray.

无复制

简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同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]]