深浅拷贝和赋值的区别
lis1 = [1, 2, 3, 4, ["xxx", "ahaha"]] # 以一个列表lis1为例 lis2 = lis1 # lis2用来显示赋值的效果 lis3 = lis1.copy() # lis3用来显示浅拷贝的效果 print(id(lis1), id(lis2), id(lis3)) # 2405339158472 2405339158472 2405339158600 # 可以看到lis1和2的内存地址相同,lis3不同 # 得到结论:赋值后lis1与lis2等效,指向同一个数据 print(id(lis1[0]), id(lis1[1]), id(lis1[2]), id(lis1[4])) print(id(lis2[0]), id(lis2[1]), id(lis2[2]), id(lis2[4])) print(id(lis3[0]), id(lis3[1]), id(lis3[2]), id(lis3[4])) # 1444529840 1444529872 1444529904 2405339158728 # 可以看到未进行数据修改时,第一层的内存地址都相同 # 1444529840 1444529872 1444529904 2405339158728 # 1444529840 1444529872 1444529904 2405339158728 lis1[0] = 5 # 接下来对lis1的数据进行修改 lis1[4][0] = "yyy" # 接下来对lis1的数据进行修改 print(lis3) # 1未变为5,列表内数据改变 # [1, 2, 3, 4, ['yyy', 'ahaha']] print(lis1[4] is lis3[4]) # 浅拷贝备份中的可变数据类型等效于原函数内的数据 # True
浅拷贝只是直接将所有数据指向的内存地址复制一份关联到自己创建的数据,如图,创建了0xffff6666这个列表对象,但是列表内的指向不变
当修改不可变数据类型时原函数指向变化,浅拷贝指向不变,浅拷贝不受影响
当修改列表内的容器类型内的数据时,原列表与copy的列表都会受影响
浅拷贝只能拷贝第一层的内存地址,当第一层的内存地址不变但内部数据改变时会受到影响
import copy lis1 = [1, 2, 3, 4, ["xxx", "ahaha"]] lis3 = copy.deepcopy(lis1) # 深拷贝 print(lis1 is lis3) # False print(id(lis1[0]), id(lis1[1]), id(lis1[2]), id(lis1[4])) print(id(lis3[0]), id(lis3[1]), id(lis3[2]), id(lis3[4])) 1444529840 1444529872 1444529904 2407768538760 1444529840 1444529872 1444529904 2407767069960
深拷贝中可以看到对lis1内的小列表独立制造了一份,与原列表无关,如果在图中就是创建了一个0xffff5555的新列表,其他指向不变
不可变数据直接关联的形式是由于更改原数据后原数据会有新的内存空间,不会修改原有空间,并且能节省空间
结论:
浅拷贝是直接将所有数据的内存地址复制一份关联到自己创建的数据
深拷贝是会将可变不可变数据进行区分,并且将可变数据类型重新创建一份,不可变数据则直接关联到原数据