在对数组进行某些操作的时候,会生成一个新的数组作为结果返回,新数组存放的数据有时是原数组元素的一个拷贝,修改其中的数据不会影响到原数组,他们是相互独立的;有时却又和原数组是数据共享的,修改其中一个数组的数据,另外一个也变了。

前者生成的是数组的拷贝,后者生成的是数组的一个视图

视图

在前面遇到的很多操作,比如转置,修改尺寸,切片等操作都只是返回了原数组的一个视图作为结果。虽然用id()函数查看它们,返回的是不同的编号,这仅仅意味着它们是不同的对象,但不能保证其中存储的数据是独立的。

  1. import numpy as np
  2. """
  3. 1. 转置
  4. """
  5. a = np.array([[1, 2], [3, 4]])
  6. b = a.T # 返回的是 a 的一个视图
  7. print(id(a), id(b)) # 2668490408304 2668490408384
  8. a[0, 0] = 666 # 修改 a,b 也修改了
  9. print(b)
  10. # [[666 3]
  11. # [ 2 4]]
  12. """
  13. 2. 修改尺寸
  14. """
  15. a = np.arange(4)
  16. b = a.reshape(2, 2)
  17. a[0] = 666
  18. print(b)
  19. # [[666 3]
  20. # [ 2 4]]
  21. """
  22. 3. 切片
  23. """
  24. a = np.arange(4)
  25. b = a[:2] # array([0, 1])
  26. b[0] = 666
  27. print(a) # [666 1 2 3]

几种区分方式

  1. import numpy as np
  2. """
  3. ndarray.base
  4. 如果对象的内存来自其他对象,则返回那个对象,否则返回 None
  5. """
  6. a = np.arange(4)
  7. b = a[::]
  8. print(a.base is None) # True
  9. print(b.base is a) # True
  10. """
  11. ndarray.flags.owndata
  12. flags 属性里存储了很多数组内存布局的的一些信息
  13. flags.owndata 很直观,表示是否拥有真正的数据
  14. """
  15. print(a.flags.owndata) # True
  16. print(b.flags.owndata) # False 数据相当于是从 a 那边「借」过来的

拷贝

如果有时确实想得到有完全独立数据的新数组,这时就可以使用ndarray.copy()方法,在前面「数组的索引」小节介绍过。

  1. import numpy as np
  2. a = np.arange(6).reshape(2, 3)
  3. b = a.T.copy()
  4. print(b.base) # None
  5. print(a.flags.owndata) # True