python中的赋值、深拷贝和浅拷贝
在python中经常要对list进行复制,深拷贝和浅拷贝的区别在于,从原本的list中复制出来的新的new_list,修改其中任何一个是否会对原来的list造成影响?即两个list在内存中是否存储在同一块内存空间,这也是区分深拷贝和浅拷贝的重要依据
1、赋值操作
直接用赋值=来进行赋值,这两个列表时等价的,在内存中是同一块内存,修改其中的任何一个都会影响另一个列表
old_lsit = [1,2,3,4,[4,5,6,7]] new_list = old_lsit print(id(old_lsit)) print(id(new_list)) # 从打印的内存地址看 两个列表指向的内存地址完全一样,所以更改其中的任何一个对另一个就会造成影响 old_lsit[0] = 99 old_lsit[-1][0] = 66 new_list[1] = 11 new_list[-1][-1] = 88 print(old_lsit) print(new_list) 打印结果: 14583368 14583368 [99, 11, 3, 4, [66, 5, 6, 88]] [99, 11, 3, 4, [66, 5, 6, 88]]
2、浅拷贝
实现浅拷贝的方法1)切片2)copy模块中的copy方法3)列表生成式
浅拷贝之所以称为浅拷贝,原因是它只拷贝了一层,拷贝了最外围的对象本身,对于嵌套的可变数据类型,它只拷贝了其内存地址的引用
浅拷贝分为两种情况:
1)当浅拷贝的对象为不可变数据类型的时候,和赋值时一样的,都是拷贝的对象的引用,但是对于不可变数据对象本身来讲,当值改变时其内存地址会发生变化,所以两者不会相互影响
a = 10 b = copy.copy(a) print(id(a),a) print(id(b),b) a = 99 print(id(a),a) print(id(b),b) 结果: 1792898336 10 1792898336 10 1792899760 99 1792898336 10
2)当浅拷贝的对象为list dict 集合可变数据类型的时候,当可变数据类型是单一类型没有嵌套的时候,浅拷贝也不会相互影响,只有当有嵌套的时候,比如list中嵌套list 改变嵌套的list值会相互影响
old_lsit = [1,2,3,4,[4,5,6,7]] new_list = old_lsit[:] print(id(old_lsit),old_lsit) print(id(new_list),new_list) old_lsit[0] = 99 old_lsit[-1][-1] =88 print(id(old_lsit),old_lsit) print(id(new_list),new_list) # 从打印来看 对外围的实现了深拷贝,而嵌套的list还是浅拷贝 打印结果: 1919616 [1, 2, 3, 4, [4, 5, 6, 7]] 6653952 [1, 2, 3, 4, [4, 5, 6, 7]] 1919616 [99, 2, 3, 4, [4, 5, 6, 88]] 6653952 [1, 2, 3, 4, [4, 5, 6, 88]]
1)切片
old_lsit = [1,2,3,4,[4,5,6,7]] new_list = old_lsit[:] print(id(old_lsit),old_lsit) print(id(new_list),new_list) old_lsit[0] = 99 old_lsit[-1][-1] =88 print(id(old_lsit),old_lsit) print(id(new_list),new_list) # 从打印来看 对外围的实现了深拷贝,而嵌套的list还是浅拷贝 打印结果: 1919616 [1, 2, 3, 4, [4, 5, 6, 7]] 6653952 [1, 2, 3, 4, [4, 5, 6, 7]] 1919616 [99, 2, 3, 4, [4, 5, 6, 88]] 6653952 [1, 2, 3, 4, [4, 5, 6, 88]]
2)使用copy模块中的copy函数
old_lsit = [1,2,3,4,[4,5,6,7]] new_list = copy.copy(old_lsit) print(old_lsit) print(new_list) old_lsit[0] = 22 old_lsit[-1][-1] = 99 print(old_lsit) print(new_list)# 也是最外围实现了深拷贝,内部嵌套的list是浅拷贝,改变内部嵌套的list的值会相互影响
打印结果:
[1, 2, 3, 4, [4, 5, 6, 7]]
[1, 2, 3, 4, [4, 5, 6, 7]]
[22, 2, 3, 4, [4, 5, 6, 99]]
[1, 2, 3, 4, [4, 5, 6, 99]]
3)列表生成式
old_lsit = [1,2,3,4,[4,5,6,7]] new_list = [i for i in old_lsit] print(id(old_lsit),old_lsit) print(id(new_list),new_list) old_lsit[0] = 99 old_lsit[-1][-1] = 100 print(id(old_lsit),old_lsit) print(id(new_list),new_list) 打印结果: 2443904 [1, 2, 3, 4, [4, 5, 6, 7]] 7898216 [1, 2, 3, 4, [4, 5, 6, 7]] 2443904 [99, 2, 3, 4, [4, 5, 6, 100]] 7898216 [1, 2, 3, 4, [4, 5, 6, 100]]
2、深拷贝
和浅拷贝对应,深拷贝拷贝了对象的所有元素,无论多少层嵌套,深拷贝出来是一个全新的对象,和之前的对象无任何关系
实现方法:copy模块中的deepcopy()函数
old_lsit = [1,2,3,4,[4,5,6,7]] new_list = copy.deepcopy(old_lsit) print(id(old_lsit),old_lsit) print(id(new_list),new_list) old_lsit[0]=99 old_lsit[-1][-1] =100 print(id(old_lsit),old_lsit) print(id(new_list),new_list) 打印结果: 11240952 [1, 2, 3, 4, [4, 5, 6, 7]] 11024984 [1, 2, 3, 4, [4, 5, 6, 7]] 11240952 [99, 2, 3, 4, [4, 5, 6, 100]] 11024984 [1, 2, 3, 4, [4, 5, 6, 7]]