深浅拷贝

涉及到深浅拷贝,我们先不解释这个问题,先来看一下复制的问题,这里的复制不再是简单的字符串之间的复制,而是列表之间的复制

好,首先提出一个需求:将一个列表复制一份,且要求复制与被复制之间的修改不能相互影响,一个很简单的实现:

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内容的变化,继续用一张图来说明一下:

 这里就是浅拷贝的秘密所在,因为我们前面说了是第一层拷贝,这里我们的第二层指针,相当于共享的,也就是别名。于是任何地方的修改都会导致其他地方的变化

原文地址:https://www.cnblogs.com/panlei3707/p/8398373.html