浅拷贝:在含有多层对象的字典,列表,集合中,浅拷贝只拷贝父对象,不会拷贝父对象内部的可变子对象。语法:copy.copy()
深拷贝:只要被拷贝对象含有可变子对象,程序就会重新申请一块内存空间把被拷贝对象的值复制一份存放到该内存空间中。语法:copy.deepcopy()
首先, 浅拷贝不是赋值,赋值与浅拷贝并不相等。赋值是在变量和值之间建立引用,并不是拷贝引用指向的数据,而浅拷贝就是拷贝引用指向的数据给另外一个引用。两者存在本质区别。
a = 1
b = a
c = 1
c = 2
上面的第一和第二语句说明变量a和变量b引用相等,即存储的值都是指向内存空间值为1的地址。第三句和第四句说明c重新建立了引用,由于一个变量只能引用一个值,所以c只会指向内存空间存储值为2的地址。
# 浅拷贝举例1
temp_var_one = [1, 2, "olivier"]
temp_var_two = copy.copy(temp_var_one)
# temp_var_two = temp_var_one # 赋值和copy的区别:赋值是引用相等, copy是拷贝一份地址的值到另一个引用
print(id(temp_var_one), id(temp_var_two)) # 用赋值id相等, 用copy时id不等
temp_var_two[2] = "olivier_"
print(temp_var_one, temp_var_two) # [1, 2, 'olivier'] [1, 2, 'olivier_']
# 浅拷贝举例2
temp_var_three = [1, 2, {1, 3, 2}]
temp_var_four = copy.copy(temp_var_three)
temp_var_four[2].add(4)
print(temp_var_three, temp_var_four) # [1, 2, {1, 2, 3, 4}] [1, 2, {1, 2, 3, 4}]
1)从赋值id相同,浅拷贝id不同的结果可以看出赋值只是创建相同的引用给新的变量,而浅拷贝是赋值内存空间中的数据给另外一个变量。
2)当父级对象只含有不可变数据类型时,因为不可变数据类型被修改时会重新开辟内存地址并储存,所以修改浅拷贝的对象并不会影响到被拷贝的对象的值,如浅拷贝举例1。
3)当父级对象含有可变数据类型时,因为浅拷贝只复制了可变数据类型对象的引用,并没有重新申请内存空间,所以修改浅拷贝对象的可变数据类型的值时,也会导致被拷贝的对象的可变数据类型的值一起变化。
# 深拷贝举例1
temp_var_one = [1, 2, "olivier"]
temp_var_two = copy.deepcopy(temp_var_one)
temp_var_two[2] = "olivier_"
print(temp_var_one, temp_var_two) # [1, 2, 'olivier'] [1, 2, 'olivier_']
# 深拷贝举例2
temp_var_three = [1, 2, {1, 3, 2}]
temp_var_four = copy.deepcopy(temp_var_three)
temp_var_four[2].add(4)
print(temp_var_three, temp_var_four) # [1, 2, {1, 2, 3}] [1, 2, {1, 2, 3, 4}]
上图的深拷贝的例子,当进行深拷贝时,会针对被拷贝对象的所有可变数据类型进行真正的值拷贝到另一块内存空间当中,所有当拷贝对象发生变化时,不会影响被拷贝对象的值。