在对数组进行某些操作的时候,会生成一个新的数组作为结果返回,新数组存放的数据有时是原数组元素的一个拷贝,修改其中的数据不会影响到原数组,他们是相互独立的;有时却又和原数组是数据共享的,修改其中一个数组的数据,另外一个也变了。
前者生成的是数组的拷贝,后者生成的是数组的一个视图。
视图
在前面遇到的很多操作,比如转置,修改尺寸,切片等操作都只是返回了原数组的一个视图作为结果。虽然用id()
函数查看它们,返回的是不同的编号,这仅仅意味着它们是不同的对象,但不能保证其中存储的数据是独立的。
import numpy as np
"""
1. 转置
"""
a = np.array([[1, 2], [3, 4]])
b = a.T # 返回的是 a 的一个视图
print(id(a), id(b)) # 2668490408304 2668490408384
a[0, 0] = 666 # 修改 a,b 也修改了
print(b)
# [[666 3]
# [ 2 4]]
"""
2. 修改尺寸
"""
a = np.arange(4)
b = a.reshape(2, 2)
a[0] = 666
print(b)
# [[666 3]
# [ 2 4]]
"""
3. 切片
"""
a = np.arange(4)
b = a[:2] # array([0, 1])
b[0] = 666
print(a) # [666 1 2 3]
几种区分方式
import numpy as np
"""
ndarray.base
如果对象的内存来自其他对象,则返回那个对象,否则返回 None
"""
a = np.arange(4)
b = a[::]
print(a.base is None) # True
print(b.base is a) # True
"""
ndarray.flags.owndata
flags 属性里存储了很多数组内存布局的的一些信息
flags.owndata 很直观,表示是否拥有真正的数据
"""
print(a.flags.owndata) # True
print(b.flags.owndata) # False 数据相当于是从 a 那边「借」过来的
拷贝
如果有时确实想得到有完全独立数据的新数组,这时就可以使用ndarray.copy()
方法,在前面「数组的索引」小节介绍过。
import numpy as np
a = np.arange(6).reshape(2, 3)
b = a.T.copy()
print(b.base) # None
print(a.flags.owndata) # True