NumPy之浅拷贝和深拷贝

系列文章

一次性搞定NumPy入门基础知识
NumPy之操控ndarray的形状
NumPy之浅拷贝和深拷贝
NumPy之索引技巧

概述

NumPy经常会操作size很大的数据结构,如果不加小心,会产生很大的内存和性能浪费,因此要理解操作中的各种行为,根据实际情况选择最合理的方法。

完全没有拷贝

如果只是进行简单的赋值操作,是不会发生拷贝行为的。

>>> a = np.arange(12)
>>> b = a            
>>> b is a           # a和b仅仅是同一个对象的不同名字
True
>>> b.shape = 3,4 
>>> a.shape
(3, 4)

这是由Python语言层面保证的,在进行赋值操作时,Python进行的时引用传递,两个变量指向同一块内存区域。

>>> def f(x):
...     print(id(x))
...
>>> id(a)                           
148293216
>>> f(a)
148293216

视图或者浅拷贝

不同的ndarray对象可以共享相同的数据区。view方法可以新建一个新的ndarray,这个新的ndarray和原始的ndarray不是一个对象(意味着除了数据区,其他一些属性,例如形状,都可以是不同的):

>>> c = a.view()
>>> c is a                               
False                                      # c和a并不是一个对象
>>> c.base is a                        # c的数据来自于a
True
>>> c.flags.owndata            
False
>>>
>>> c.shape = 2,6                      # 修改c的形状属性并不会影响a
>>> a.shape
(3, 4)
>>> c[0,4] = 1234                      # 由于二者共享数据区,修改c的数据也会影响到a
>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])

注意,索引操作返回的就是原始ndarray的一个view:

>>> s = a[ : , 1:3]
>>> s
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])
>>> s[:] = 10
>>> s
array([[10, 10],
       [10, 10],
       [10, 10]])
>>>
>>> a                   # 修改s的数据区也会影响到a中的相应数据
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

深拷贝

copy方法可以生成一个完整的新ndarray对象,这个ndarray对象和原始的ndarray没有任何关系:

>>> d = a.copy()                          # 新的对象,新的数据区
>>> d is a
False
>>> d.base is a                           
False
>>> d[0,0] = 9999
>>> a                                        # 修改d的数据区并不会影响到a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

一个典型的应用场景是:如果使用索引操作后,原始的ndarray已经不需要了,那么就可以首先进行一个深拷贝,然后销毁原始ndarray,这样会减少内存消耗。

>>> a = np.arange(int(1e8))
>>> b = a[:100].copy()
>>> del a  # a占据的内存会被释放
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值