【Python】Numpy 与 标准python中的=,视图(浅拷贝),深拷贝

【Python】Numpy 与 标准python中的=,视图(浅拷贝),深拷贝

一,= (完全不复制)

1,NumPy

In [2]: a = np.arange(8)                                                                                                 
In [3]: a                                                                                                                
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7])
In [4]: id(a)                                                                                                            
Out[4]: 140297255040544
In [5]: b = a                                                                                                            
In [6]: b                                                                                                                
Out[6]: array([0, 1, 2, 3, 4, 5, 6, 7])
In [7]: id(b)                                                                                                            
Out[7]: 140297255040544
In [8]: b[0] = -1                                                                                                        
In [9]: a           # a和b是同一个ndarray对象的两个名字,对b的任何操作都会影响a                                                                                                    
Out[9]: array([-1,  1,  2,  3,  4,  5,  6,  7])
In [17]: b.shape = 2,4                                                                                                   
In [18]: b                                                                                                               
Out[18]: 
array([[-1,  1,  2,  3],
       [ 4,  5,  6,  7]])
In [19]: a        # 也会改变a的形状                                                                                                        
Out[19]: 
array([[-1,  1,  2,  3],
       [ 4,  5,  6,  7]])

(1)不创建新的数组,同个内存地址。
(2)新旧数组是用一个对象的不同标签(名字)而已。
(3)改变其中一个,另一个也会跟着变化,包括改变数组中的数据,以及数组的形状
2,标准python
赋值本质上 是对象之间的引用传递而已。也就是多个对象指向同一个数据空间。

In [31]: a                                                                                                               
Out[31]: [1, 2, 3, 4, [-1, -2]]
In [32]: b = a                                                                                                           
In [33]: id(a)                                                                                                           
Out[33]: 140297286164616
In [34]: id(b)                                                                                                           
Out[34]: 140297286164616
In [35]: b[0] = -1                                                                                                       
In [36]: b[4].append(-3)   #嵌套的列表也是相同地址,修改后也会影响到a                                                                                             
In [37]: b                                                                                                               
Out[37]: [-1, 2, 3, 4, [-1, -2, -3]]
In [38]: a                                                                                                               
Out[38]: [-1, 2, 3, 4, [-1, -2, -3]]
二,视图(浅拷贝)

1,numpy中的视图

In [39]: a = np.arange(8)                                                                                                
In [40]: b = a[:]      #切分的结果为原数组的视图,非复制                                                                                                  
In [41]: b                                                                                                               
Out[41]: array([0, 1, 2, 3, 4, 5, 6, 7])
In [42]: a                                                                                                               
Out[42]: array([0, 1, 2, 3, 4, 5, 6, 7])
In [43]: id(a)                                                                                                           
Out[43]: 140297254632064
In [44]: id(b)                                                                                                           
Out[44]: 140297254522352         # a,b的内存地址不同 
In [45]: a is b                                                                                                          
Out[45]: False
In [46]: b[0] = -1                                                                                                       
In [47]: b                                                                                                               
Out[47]: array([-1,  1,  2,  3,  4,  5,  6,  7])
In [48]: a                                                                                                               
Out[48]: array([-1,  1,  2,  3,  4,  5,  6,  7])    #修改b 也会作用于a
In [49]: np.may_share_memory(a, b)                                                                                       
Out[49]: True              # a,b共享内存
In [50]: a.flags.owndata                                                                                                 
Out[50]: True          # a 拥有数据
In [51]: b.flags.owndata                                                                                                 
Out[51]: False         # b 不拥有数据
In [52]: b.base is a                                                                                                     
Out[52]: True        # b 基于 a
In [53]: b.shape = 4,2                                                                                                   
In [54]: b                                                                                                               
Out[54]: 
array([[-1,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7]])
In [55]: a                                                                                                               
Out[55]: array([-1,  1,  2,  3,  4,  5,  6,  7])    # 数据形状的改变不影响

(1)不同的两个对象,可以理解为两个存储了指向同一个内存块的指针(np.may_share_memory(a, b) 为 True)。
(2)改变一个的形状不会改变另一个,只是数据共享。
(3)改变一个数据会同时改变另一个:数据共享,上面的demo中,b = a[:]会创建一个新的对象b(所以说 id 和a不一样),但是b的数据完全来自于a,和a保持完全一致(b.base is a 为 True),换句话说,b的数据完全由a保管(a.flags.owndata 为 True),他们两个的数据变化是一致的。
(4)可以理解为数据库中的视图与表的关系,视图不存储数据,表中存储数据,通过视图可以修改表中的数据。

2,标准python 浅拷贝

In [56]: a = [1,2,[-1,-2]]                                                                                               
In [57]: b = a[:]        #等价于b = a.copy()                                                                                                   
In [58]: id(a)                                                                                                           
Out[58]: 140297111902920
In [59]: id(b)                                                                                                           
Out[59]: 140297254461960       # a,b为不同对象
In [60]: [id(x) for x in a]                                                                                              
Out[60]: [9330720, 9330752, 140297125092744]
In [61]: [id(x) for x in b]                                                                                              
Out[61]: [9330720, 9330752, 140297125092744]  #第一层元素的地址不同,但是深层原始相同地址
In [62]: b[0] = 0                                                                                                        
In [63]: b                                                                                                               
Out[63]: [0, 2, [-1, -2]]
In [64]: a                                                                                                               
Out[64]: [1, 2, [-1, -2]]
In [65]: b[2].append(-3)                                                                                                 
In [66]: b                                                                                                               
Out[66]: [0, 2, [-1, -2, -3]]
In [67]: a                                                                                                               
Out[67]: [1, 2, [-1, -2, -3]]

浅拷贝可以理解为藕断丝连,浅拷贝只拷贝第一层数据,既节省了内存空间和拷贝时间,速度更快,但存在深层数据还是同个地址,修改会受到影响。
当我们使用下面的操作的时候,会产生浅拷贝的效果:
使用切片[:]操作 b = a[:]
使用工厂函数(如list/dir/set) b = list(a)
使用copy模块中的copy()函数 b = a.cppy ,需要导入copy

三,深拷贝

1,numpy 深拷贝

In [95]: a = np.arange(8)                                                                                                
In [96]: b = a.copy()                                                                                                    
In [97]: a is b                                                                                                          
Out[97]: False
In [98]: b.base is a                                                                                                     
Out[98]: False
In [99]: a.flags.owndata                                                                                                 
Out[99]: True
In [100]: b.flags.owndata                                                                                                
Out[100]: True
In [101]: np.may_share_memory(a,b)                                                                                       
Out[101]: False

深拷贝后,两个数组相互独立,拥有各自的数据,不在共享内存数据。修改形状和数据都互不影响。

2,标准python 深拷贝

In [72]: import copy                                                                                                     
In [83]: a                                                                                                               
Out[83]: [1, 2, [-1, -2, -3]]
In [84]: b = copy.deepcopy(a)                                                                                            
In [85]: [id(x) for x in a]                                                                                              
Out[85]: [9330720, 9330752, 140297125092744]
In [86]: [id(x) for x in b]                                                                                              
Out[86]: [9330720, 9330752, 140297111147976]  #  不可变对象id值一样,可变对象id值不一样,
In [87]: b[1] = 0                                                                                                        
In [88]: b[2][1] = 0                                                                                                     
In [89]: [id(x) for x in a]                                                                                              
Out[89]: [9330720, 9330752, 140297125092744]
In [90]: [id(x) for x in b]                                                                                              
Out[90]: [9330720, 9330688, 140297111147976] #不可变对象只要值改变就会指向新地址,不会影响与其值改变

参考
https://www.cnblogs.com/eczhou/p/7860668.html
https://blog.csdn.net/weixin_43965642/article/details/85770177

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值