继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

python 中的深浅复制

暮色呼如
关注TA
已关注
手记 247
粉丝 86
获赞 309

前言

想起来写这篇博客是因为这段时间学习 js 的时候涉及到了变量的深浅复制问题,然后想先把 python 中的深浅复制理解的更深入一些,再写 js 中的深浅复制,因为 python 对我来说已经很熟悉了。

在 python 中,标识一个对象的唯一身份有三个状态:对象的 id(内存地址),对象类型,对象值。

赋值

  • 赋值是将一个对象的地址赋值给一个变量,使得变量指向该内存地址;

  • 修改不可变对象时(str、tuple、int)需要开辟新的内存空间;

  • 修改可变对象时(list、dict、set)不需要开辟新的内存空间。

赋值是将 id 重新赋值给了一个新的变量,引用计数加1。

浅拷贝

浅拷贝只是拷贝父对象,而对于父对象中的子对象并不会进行拷贝。

a = {1: [1, 2, 3]}
b = a.copy()
a['name'] = 'musibii'a # {1: [1, 2, 3], 'name': 'musibii'}b # {1: [1, 2, 3]}a[1].append(4)
a # {1: [1, 2, 3, 4], 'name': 'musibii'}b # {1: [1, 2, 3, 4]}

也就是说浅拷贝将a的值复制到一个新的内存空间,并将内存地址赋值给 b,所以对 a 对象添加新的属性,b 并不会改变;但是因为浅拷贝只是拷贝了一层,对于子对象的内存空间是原对象的内存引用,所以修改 a 相应的 b 中也会改变。

浅拷贝只拷贝父对象,不会拷贝对象内部的子对象。

深拷贝

深拷贝完全赋值被复制对象的元素,不是复制内存地址,是开辟新的内存空间将被复制对象的值放在了新的内存空降中,并将新的内存地址指向了新的变量,这样的话,修改原对象不会对新的对象产生影响。

深拷贝是在另一块地址中创建一个新的变量,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本。

在Python 中深拷贝需要引入 copy 模块:

import copy
c = copy.deepcopy(a)
c # {1: [1, 2, 3], 'name': 'musibii'}a[1].append(4)
a # {1: [1, 2, 3, 4], 'name': 'musibii'}c # {1: [1, 2, 3], 'name': 'musibii'}

解析

  1. b = a:赋值引用,a 和 b 都指向同一个对象

5c2e063a0001bdfc03540246.jpg

  1. b = a.copy():浅拷贝,a 和 b 是一个独立的对象,但他们的子对象还是指向同一个对象(引用)。

5c2e063a000195c603720260.jpg

  1. b = copy.deepcopy(a):深拷贝,a 和 b 完全拷贝了父对象及其子对象,两者完全独立。

5c2e063a0001524e03990266.jpg

更多实例

import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
 b = a                       #赋值,传对象的引用c = copy.copy(a)            #对象拷贝,浅拷贝d = copy.deepcopy(a)        #对象拷贝,深拷贝
 a.append(5)                 #修改对象aa[4].append('c')            #修改对象a中的['a', 'b']数组对象
 print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )

输出

('a = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('b = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('c = ', [1, 2, 3, 4, ['a', 'b', 'c']])
('d = ', [1, 2, 3, 4, ['a', 'b']])

以上部分参考

菜鸟教程

原文出处:https://www.cnblogs.com/zuanzuan/p/10185075.html  

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP