list1 = [[1,2],3,4] list2 = list1.copy() print(list2) list2[1] = 6 print(list2) print(list1)
结果:
[[1, 2], 3, 4]
[[1, 2], 6, 4]
[[1, 2], 3, 4]
修改list2的第二项(整型),只有list2发生变法,list1不变
list1 = [[1,2],3,4] list2 = list1.copy() print(list2) list2[0][0] = 8 print(list2) print(list1)
结果:
[[1, 2], 3, 4]
[[8, 2], 3, 4]
[[8, 2], 3, 4]
修改list2的第一项(列表),list2发生变法,list1也发生变化
如何解释这样的一个结果?
如左图(修改前):
对于list1来说,list1[0],list1[1],list1[2]的指针指向三个内存地址,对应[1,2],3,4,而list1[0][0]和list1[0][1]的指针又指向两个内存地址,对应1,2,总计五条绿线
同样的,由于list2是由list1浅拷贝而来,list2[0],list2[1],list2[2]的指针指向相同的三个内存地址,总计三条红线
如右图(修改后):
list2[0][0] = 8的操作,将开辟一个新的内存空间(右下的黄框8),将使list2[0][0]的指针指向8,这将影响list1[0][0]的指针变化,也指向8,所以list1和list2都发生了变化。
而当修改list2的整型元素(list2[1] = 6)时,同样会开辟一个新的内存空间,使list2[1]的指针指向6,而list1[1]的指针没有发生变化,还是指向3,所以list2变了list1没变。
总结:
拷贝就是一个变量的值传给另外一个变量。在python 中 id()方法可以查看存放变量的内存地址。
浅拷贝是指把存放变量的地址值传给被赋值,最后两个变量引用了同一份地址,即两个指针指向同一个内存空间。在python中引用copy模块,copy模块中有copy()方法,调用它完成变量的浅copy。
深拷贝是指被赋值的变量开辟了另一块地址用来存放要赋值的变量的值(内容)。在python中引用copy模块,copy模块中有deepcopy()方法,调用它完成变量的深copy。
使用copy模块的拷贝功能的时候,会根据当前拷贝的数据类型,可变类型和不可变类型有不同的处理方式。
=赋值:数据完全共享
是在内存中指向同一个对象,不论是可变类型(比如列表)或不可变类型(比如字符串),修改了其中一个,另一个必定改变。
浅拷贝:数据半共享
只拷贝成功第一层,第二层的数据并没有拷贝成功,而只是指向了第二层数据的内存地址,所以第二层只是共享,所以如果第二层的数据发生变化,那么都会跟着变化。
深拷贝:数据完全不共享
深拷贝就是完完全全复制了一份,且数据不会互相影响,因为内存不共享,改了一个另一个都不变化。