前提
存在一个列表:list1=['egon', 'lxx', [1,2]]
list1的内存图示:
列表赋值操作,二者不可分割
list2=list1
,此操作使二者不可分割,一个改动另一个也改动,因为内存地址完全相同,指向的值也相同
['egon', 'lxx', [1,2]
list2 = list1
list1[0] = 'EGON'
print(list2)
>>>>
['EGON', 'lxx', [1,2]
此操作不是列表的拷贝,只是赋值操作。
需求:
- 拷贝一下原列表,产生一个新列表
- 想让两个列表完全独立开(针对的是列表的修改操作,而不是读操作)
如何拷贝列表
一、浅拷贝copy
- 拷贝完成后的列表完全相同
list3 = list1.copy()
print(id(list1[0], id(list1[1]), id(list1[2]))
print(id(list3[0], id(list3[1]), id(list3[2]))
>>>>
2031475499056 2031475460976 2031475448448
2031475499056 2031475460976 2031475448448
- 修改list1的值,发现针对不可变类型的数值没变,但是针对可变类型的数值跟着一起变化
实验一:
list1[0] = 'EGON'
list1[1] = 'LXX'
list1[2] = 123 # 将第三个列表整体修改为不可变类型
print(list1)
print(list3)
>>>>
['EGON', 'LXX', 123]
['egon', 'lxx', [1, 2]] # list3没有改变
实验二:
list1[0] = 'EGON'
list1[1] = 'LXX'
list1[2][0] = 111 # 将第三个列表的每个可变类型进行修改
list1[2][1] = 222 # 将第三个列表的每个可变类型进行修改
print(list1)
print(list3)
>>>>
['EGON', 'LXX', [111, 222]]
['egon', 'lxx', [111, 222]] # list3的第三个列表里的值跟着变化
浅拷贝概念:
把原列表的第一层内存地址不加区分完全copy一份给新列表。
如果原列表全是不可变类型,修改没有问题;但是如果原列表有可变类型,修改可变类型的值将会同步修改新列表。
二、深拷贝deepcopy
综合实验1与实验2得出,要想copy得到的新列表与原列表的改操作完全独立开,必须有一种可以****区分开可变类型和不可变类型的copy机制****,这就是深拷贝。
- 针对可变类型,深拷贝会copy一个内存地址不同的数据
import copy
list1 = ['egon', 'lxx', [1, 2]]
list3 =copy.deepcopy(list1)
print(id(list1))
print(id(list3))
# 不可变 不可变 可变
print(id(list1[0]), id(list1[1]), id(list1[2]))
print(id(list3[0]), id(list3[1]), id(list3[2]))
>>>>
2396863448128
2396866008128
2396863143984 2396863314352 2396865996608
2396863143984 2396863314352 2396863379712
- 可变类型中的值内存地址相同
print(id(list1[2][0]), id(list1[2][1]))
print(id(list3[2][0]), id(list3[2][1]))
>>>>
3075299764528 3075299764560
3075299764528 3075299764560
- 修改操作,深拷贝的列表即使是可变数据类型也不会收到影响
list1[0] = 'EGON'
list1[1] = 'LXX'
list1[2][0] = 111
list1[2][1] = 222
print(list1)
print(list3)
>>>>
['EGON', 'LXX', [111, 222]]
['egon', 'lxx', [1, 2]]
总结
浅拷贝:只针对列表的第一层进行拷贝,会将数据的第一层所有数据的内存地址进行拷贝,导致如果是可变类型数据会与原列表分割不开,原列表修改可变数据后会同步修改浅拷贝的列表对应的数据。
深拷贝:会对可变和不可变类型加以区分,针对可变数据类型拷贝出来的内存地址不相同,这样原列表即使修改了可变数据类型的数据也不会影响深拷贝后的列表。