这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战
Numpy中赋值操作有时候是数据复制(返回新对象),有时候却是引用.
下面的数组赋值运算是不会复制数据的,只是引用:
In [37]: data = np.arange(6)
In [38]: data.shape Out[38]: (6,)
In [39]: data Out[39]: array([0, 1, 2, 3, 4, 5])
In [40]: data2 = data
In [41]: data2 is data Out[41]: True
In [42]: data.resize(2,3)
In [43]: data Out[43]: array([[0, 1, 2], [3, 4, 5]])
In [44]: data2 Out[44]: array([[0, 1, 2], [3, 4, 5]])
Numpy的view方法(视图的方法)可以创建共享相同数据的不同数组, 改变某个值,共享这些数据的数组都会受到影响:
In [45]: data Out[45]: array([[0, 1, 2], [3, 4, 5]])
In [46]: data2 = data.view()
In [47]: data2 is data Out[47]: False
In [48]: data2.shape = 1,-1
In [49]: data Out[49]: array([[0, 1, 2], [3, 4, 5]])
In [50]: data2 Out[50]: array([[0, 1, 2, 3, 4, 5]])
In [51]: data2.base is data Out[51]: True
In [52]: data2[0, 2] = 999
In [53]: data Out[53]: array([[ 0, 1, 999], [ 3, 4, 5]])
In [54]: data2 Out[54]: array([[ 0, 1, 999, 3, 4, 5]])
数组切片也是返回一个视图,改变某个值,其他数组也会受影响
In [53]: data
Out[53]:
array([[ 0, 1, 999],
[ 3, 4, 5]])
In [54]: data2 Out[54]: array([[ 0, 1, 999, 3, 4, 5]])
In [55]: data3 = data2[:, 0:2]
In [56]: data3 Out[56]: array([[0, 1]])
In [57]: data3[0,0] = 888
In [58]: data3 Out[58]: array([[888, 1]])
In [59]: data Out[59]: array([[888, 1, 999], [ 3, 4, 5]])
In [60]: data2 Out[60]: array([[888, 1, 999, 3, 4, 5]])
Numpy的copy方法可以完全拷贝一个数组副本,返回新的数组对象:
In [61]: data Out[61]: array([[888, 1, 999], [ 3, 4, 5]])
In [62]: data2 = data.copy()
In [63]: data2 Out[63]: array([[888, 1, 999], [ 3, 4, 5]])
In [64]: data2[0, 0] = 666
In [65]: data2 Out[65]: array([[666, 1, 999], [ 3, 4, 5]])
In [66]: data Out[66]: array([[888, 1, 999], [ 3, 4, 5]])
所以,如果不需要原数组只需要一小部分数据,应该使用切片获得视图后调用copy方法保存新数组后, 进行del 原数组进行释放内存。
In [66]: data Out[66]: array([[888, 1, 999], [ 3, 4, 5]])
In [67]: result = data[:, 0:2].copy()
In [68]: del data
In [69]: result Out[69]: array([[888, 1], [ 3, 4]])