深浅拷贝
涉及到深浅拷贝,我们先不解释这个问题,先来看一下复制的问题,这里的复制不再是简单的字符串之间的复制,而是列表之间的复制
好,首先提出一个需求:将一个列表复制一份,且要求复制与被复制之间的修改不能相互影响,一个很简单的实现:
names_class1=['张三','李四','王五','赵六'] names_class1_copy=['张三','李四','王五','赵六']
但这时候问题来了,如果列表内容很多呢?再这样机械的复制就太naive了,有人就这样实现:
names_class1=['张三','李四','王五','赵六'] names_class1_copy=names_class1
这里可以实现复制,但无法满足复制与被复制之间的修改不能相互影响
这样只是一个简单的类似于一个起别名的操作,两个变量共享一个内存,你改我也改,并不是一个真正的复制
于是就需要用到一个方法来处理叫大数据量的复制,列表里为我们内置了copy方法:
names_class1=['张三','李四','王五','赵六',[1,2,3]] names_class1_copy=names_class1.copy() names_class1_copy[0]='zhangsan' print(names_class1) print(names_class1_copy) ''' ['张三', '李四', '王五', '赵六', [1, 2, 3]] ['zhangsan', '李四', '王五', '赵六', [1, 2, 3]] 我们可以看到对复制来的进行的修改不会导致被复制列表的修改 ''' # 见证奇迹的发生 names_class1_copy[4][2]=5 print(names_class1) print(names_class1_copy) '''运行时记得注释前面的修改 ['张三', '李四', '王五', '赵六', [1, 2, 5]] ['张三', '李四', '王五', '赵六', [1, 2, 5]] '''
当我们对 names_class1_copy[0] 进行修改时,可以看到不会对 names_class1[0] 产生修改,但当我们对 names_class1_copy[4][2] 进行修改时,可以看到 names_class1[4][2] 也发生了变化。
这里就涉及到我们的深浅拷贝的问题了
为简单起见,我们重新写一段代码演示:
s1 = [[1,2], 3, 4] s2 = s1.copy() print("id:s1",id(s1)) print("id:s2",id(s2)) print("id:s1[0],s1[1],s1[2]",id(s1[0]),id(s1[1]),id(s1[2])) print("id:s2[0],s2[1],s2[2]",id(s2[0]),id(s2[1]),id(s2[2])) print("id:s1[0][0],s1[0][1]",id(s1[0][0]),id(s1[0][1])) print("id:s2[0][0],s2[0][1]",id(s2[0][0]),id(s2[0][1])) '''结果 id:s1 1508552982856 id:s2 1508552984072 id:s1[0],s1[1],s1[2] 1508552956936 1440116256 1440116288 id:s2[0],s2[1],s2[2] 1508552956936 1440116256 1440116288 id:s1[0][0],s1[0][1] 1440116192 1440116224 id:s2[0][0],s2[0][1] 1440116192 1440116224 '''
先是输出一下各内容的地址,用图表示一下,这里可以看出copy()方法实现的是第一层的copy,也就是图中黄色箭头的部分
继续我们的代码,这次我们对内容进行修改:
s2[1] = 'pp' print(s1) print(s2) print("id:s1[1]",id(s1[1])) print("id:s2[1]",id(s2[1])) print("id:s1[2]",id(s1[2])) print("id:s2[2]",id(s2[2])) '''结果 [[1, 2], 3, 4] [[1, 2], 'pp', 4] id:s1[1] 1440116256 id:s2[1] 2112166200240 id:s1[2] 1440116288 id:s2[2] 1440116288 '''
这里的修改是将s2[1]的内容进行修改,可以看到并不会修改s1[1]的内容,这里也用图来说明一下:
继续我们的代码,这次我们对列表中的列表内容进行修改:
s2[0][1] = 'pl' print(s1) print(s2) print("id:s1[0][0],s1[0][1]",id(s1[0][0]),id(s1[0][1])) print("id:s2[0][0],s2[0][1]",id(s2[0][0]),id(s2[0][1])) '''结果: [[1, 'pl'], 3, 4] [[1, 'pl'], 'pp', 4] id:s1[0][0],s1[0][1] 1440116192 1942456009536 id:s2[0][0],s2[0][1] 1440116192 1942456009536 '''
这次对s2的修改也造成了s1内容的变化,继续用一张图来说明一下:
这里就是浅拷贝的秘密所在,因为我们前面说了是第一层拷贝,这里我们的第二层指针,相当于共享的,也就是别名。于是任何地方的修改都会导致其他地方的变化