之前也学习过深复制、浅复制,但在实际应用的时候还是会遇到一些问题。也看过一些相关的文章,但很久也没太搞明白。今天特意在做一个二维列表的复制的时候遇到了问题,再研究一些文章再实验后,终于明白了深浅复制的根本。写出来自用,也可以给需要的人一些帮助。
理解和记住什么是可变数据什么是不可变数据非常重要:
不可变数据(3个)Number(数字)、String(字符串)Tuple(元组)
可变数据(3个):List(列表)Dictionary(字典)Set(集合)
不可变数据和可变数据是浅拷贝的根本,这两个概念分不清,就无法理解浅拷贝的问题。
浅拷贝:浅拷贝仅仅是地址指向,不会开辟新空间(仅仅是最顶层开辟了新的空间,里层的元素地址还是一样的。注1)浅拷贝时,改变原始或拷贝对象的可变数据时,原始和拷贝对象的值都变化,改变不可变数据时,只有改变的值变化,原值不变。
注1:仅仅是最顶层开辟了新的空间,里层的元素地址还是一样的。原始和拷贝的id是不同的,但里面元素的id是相同的。例:
#定义一个列表
a=[[1,2],'a',2 ]#第一个元素是可变的,第二、三是是不可变的。
b=a[:]#进行浅拷贝
print(id(a),id(b)) #查询对象地址
#地址不同
1519791594760 1519791594440
#查询第一个元素地址是否相同
print(id(a[0]),id(b[0]))
#地址相同
1519791595080 1519791595080
#查询第二个元素地址是否相同
print(id(a[1]),id(b[1]))
#地址相同
1519784151112 1519784151112
改变原始或拷贝对象的可变数据时,原始和拷贝对象的值都变化,续上例:
#改变第一个元素值
a[0][0]=2
print(b)
#b的值发生了相同的变化(因为[2,2]是列表是可变数据)
[[2, 2], 'a', 2]
#改变第二个元素的值
a[1]='c'
#b的值不变。(因为‘a’为字串是不可变数据。)
[[2, 2], 'a', 2]
浅拷贝的5种方法:
1.切片浅拷贝(常用):
a=[1,2,4]
b=a[:]
2. 模块copy浅拷贝
import copy
a=[1,2,4]
b=copy.copy(a)
3.利用list()函数浅拷贝
a=[1,2,4]
b=list(a)
4.列表方法extend浅拷贝
a=[1,2,4]
b=[]
b.extend(a)
5.列表推导浅拷贝
a=[1,2,4]
b=[x for x in a]
深拷贝:真正意义的复制,原始和拷贝数据互不影响。方法也只有一种。利用copy模块中的deepcopy进行深拷贝。例:
import copy
a=[[1,2],3,4]
b=copy.copy(a)