Numpy-拷贝和视图

当计算和操作数组时,有时会将数据复制到新数组中,有时则不会。这通常是初学者混淆的根源。有三种情况
完全不复制
简单分配不会复制数组对象或其数据
In [1]:
import numpy as np
In [2]:
a=np.arange(12)
a
Out[2]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [3]:
b=a #没有新对象创建
In [4]:
b
Out[4]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [5]:
b is a # a 和 b 是对同一对象的两个名字
Out[5]:
True
In [6]:
b.shape=3,4
In [7]:
b
Out[7]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [8]:
a.shape=(4,3)
b
Out[8]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
Python将可变对象作为引用传递,因此函数调用不会复制
In [9]:
def f(x):
print(id(x))
In [10]:
id(a)
Out[10]:
92606176
In [11]:
f(a)
92606176

视图或浅拷贝
不同的数组对象可以共享相同的数据。该view方法创建一个查看相同数据的新数组对象
In [12]:
c=a.view()
In [13]:
c
Out[13]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
In [14]:
c is a
Out[14]:
False
In [15]:
c.base is a #c是a的数据的一个视图
Out[15]:
True
In [16]:
c.flags.owndata
Out[16]:
False
In [17]:
c.shape=(2,6)
c
Out[17]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11]])
In [18]:
a.shape #a的形状没有改变
Out[18]:
(4, 3)
In [19]:
c[0,4]=1234 #a的数据发生改变
In [20]:
a
Out[20]:
array([[ 0, 1, 2],
[ 3, 1234, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
切片数组会返回一个视图
In [21]:
s=a[:,1:2] #s可以理解为一个视图
In [22]:
s[:]=10
a
Out[22]:
array([[ 0, 10, 2],
[ 3, 10, 5],
[ 6, 10, 8],
[ 9, 10, 11]])
深拷贝
该copy方法生成数组及其数据的完整副本
In [23]:
d=a.copy() #一个新的对象有自己数据被创建
In [24]:
d is a
Out[24]:
False
In [25]:
d.base is a
Out[25]:
False
In [26]:
d[0,0]=9999
d
Out[26]:
array([[9999, 10, 2],
[ 3, 10, 5],
[ 6, 10, 8],
[ 9, 10, 11]])
In [27]:
a
Out[27]:
array([[ 0, 10, 2],
[ 3, 10, 5],
[ 6, 10, 8],
[ 9, 10, 11]])
有时如果不再需要原始数据,则应在切片后调用copy。例如,假设a是一个巨大的中间结果,最终结果b只包含a的一小部分,那么在用切片构造b时应该做一个深拷贝
In [28]:
a=np.arange(int(1e8))
a
Out[28]:
array([ 0, 1, 2, …, 99999997, 99999998, 99999999])
In [29]:
b=a[:100].copy()
In [30]:
del a #a的内存被释放
In [31]:
b
Out[31]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])
如果改为使用b=a[:100],则a由b引用,并且即使执行del a也会在内存中持久存在
In [32]:
d=np.arange(int(1e8))
In [33]:
c=d[:100]
In [34]:
del d
In [35]:
c
Out[35]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值