NumPy - 副本和视图

在执行函数时,其中一些返回输入数组的副本,而另一些返回视图。 当内容物理存储在另一个位置时,称为副本。 另一方面,如果提供了相同内存内容的不同视图,我们将其称为视图

无复制

简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同id()来访问它。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。

此外,一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。

示例

  1. import numpy as np
  2. a = np.arange(6)
  3. print '我们的数组是:'
  4. print a
  5. print '调用 id() 函数:'
  6. print id(a)
  7. print 'a 赋值给 b:'
  8. b = a
  9. print b
  10. print 'b 拥有相同 id():'
  11. print id(b)
  12. print '修改 b 的形状:'
  13. b.shape = 3,2
  14. print b
  15. print 'a 的形状也修改了:'
  16. print a

输出如下:

  1. 我们的数组是:
  2. [0 1 2 3 4 5]
  3. 调用 id() 函数:
  4. 139747815479536
  5. a 赋值给 b
  6. [0 1 2 3 4 5]
  7. b 拥有相同 id():
  8. 139747815479536
  9. 修改 b 的形状:
  10. [[0 1]
  11. [2 3]
  12. [4 5]]
  13. a 的形状也修改了:
  14. [[0 1]
  15. [2 3]
  16. [4 5]]

视图或浅复制

NumPy 拥有ndarray.view()方法,它是一个新的数组对象,并可查看原始数组的相同数据。 与前一种情况不同,新数组的维数更改不会更改原始数据的维数。

示例

  1. import numpy as np
  2. # 最开始 a 是个 3X2 的数组
  3. a = np.arange(6).reshape(3,2)
  4. print '数组 a:'
  5. print a
  6. print '创建 a 的视图:'
  7. b = a.view()
  8. print b
  9. print '两个数组的 id() 不同:'
  10. print 'a 的 id():'
  11. print id(a)
  12. print 'b 的 id():'
  13. print id(b)
  14. # 修改 b 的形状,并不会修改 a
  15. b.shape = 2,3
  16. print 'b 的形状:'
  17. print b
  18. print 'a 的形状:'
  19. print a

输出如下:

  1. 数组 a
  2. [[0 1]
  3. [2 3]
  4. [4 5]]
  5. 创建 a 的视图:
  6. [[0 1]
  7. [2 3]
  8. [4 5]]
  9. 两个数组的 id() 不同:
  10. a id():
  11. 140424307227264
  12. b id():
  13. 140424151696288
  14. b 的形状:
  15. [[0 1 2]
  16. [3 4 5]]
  17. a 的形状:
  18. [[0 1]
  19. [2 3]
  20. [4 5]]

数组的切片也会创建视图:

示例

  1. import numpy as np
  2. a = np.array([[10,10], [2,3], [4,5]])
  3. print '我们的数组:'
  4. print a
  5. print '创建切片:'
  6. s = a[:, :2]
  7. print s

输出如下:

  1. 我们的数组:
  2. [[10 10]
  3. [ 2 3]
  4. [ 4 5]]
  5. 创建切片:
  6. [[10 10]
  7. [ 2 3]
  8. [ 4 5]]

深复制

ndarray.copy()函数创建一个深层副本。 它是数组及其数据的完整副本,不与原始数组共享。

示例

  1. import numpy as np
  2. a = np.array([[10,10], [2,3], [4,5]])
  3. print '数组 a:'
  4. print a
  5. print '创建 a 的深层副本:'
  6. b = a.copy()
  7. print '数组 b:'
  8. print b
  9. # b 与 a 不共享任何内容
  10. print '我们能够写入 b 来写入 a 吗?'
  11. print b is a
  12. print '修改 b 的内容:'
  13. b[0,0] = 100
  14. print '修改后的数组 b:'
  15. print b
  16. print 'a 保持不变:'
  17. print a

输出如下:

  1. 数组 a
  2. [[10 10]
  3. [ 2 3]
  4. [ 4 5]]
  5. 创建 a 的深层副本:
  6. 数组 b
  7. [[10 10]
  8. [ 2 3]
  9. [ 4 5]]
  10. 我们能够写入 b 来写入 a 吗?
  11. False
  12. 修改 b 的内容:
  13. 修改后的数组 b
  14. [[100 10]
  15. [ 2 3]
  16. [ 4 5]]
  17. a 保持不变:
  18. [[10 10]
  19. [ 2 3]
  20. [ 4 5]]