需求: 1、复制原列表并产生一个新的列表 2、针对修改操作,使原列表和新列表独立开,修改其中的一个列表,另一个列表不变
list1 = ['tom', 'alex', ['albert', 'abel', 'adam']]
print(id(list1[0]), id(list1[1]), id(list1[2]))
print(id(list1[2][0]), id(list1[2][1]), id(list1[2][2]))
原列表在内存中的存储方式为: ??在通常情况下,复制一个列表会使用:list2 = list1 ,这只是赋值操作,在栈区里新创建list2 变量,将list1 的内存地址赋值给list2 。虽然可以实现需求1,对列表的读操作没有影响;但是对于需求2,如果对list1 的值做出修改,因为list2 的id与list1 的id相同,在遍历list2 值的时候,读取的是list1 的内存,结果将会是list1 修改后的值,也就是说,对于改操作,两个列表并没有独立开。
浅 Copy
??为了实现上述需求,可以调用copy() 方法。
list1 = ['tom', 'alex', ['albert', 'abel', 'adam']]
list3 = list1.copy()
??而后,通过打印每个列表id 探究原列表和新列表在内存中的存储方式。
print(id(list1), id(list3))
print(id(list1[0]), id(list1[1]), id(list1[2]))
print(id(list1[2][0]), id(list1[2][1]), id(list1[2][2]))
print(id(list3[0]), id(list3[1]), id(list3[2]))
print(id(list3[2][0]), id(list3[2][1]), id(list3[2][2]))
"""
打印结果:
id(list1):1898489782080;id(list3):1898489613760
# 原列表各项的id:
1898488642096 1898488642864 1898489783104
1898488332720 1898489830960 1898489831024
# 新列表各项的id:
1898488642096 1898488642864 1898489783104
1898488332720 1898489830960 1898489831024
"""
??可以简单的画出存储形式:
??通过打印的id 可以发现,在内存中新开辟了一个空间用来存储产生的新列表,但是从子列表的id 可以发现,并没有开辟新的内存空间用来存储子列表。此时,修改原列表某一项的值。
list1[0] = 'Tom'
list1[2][0] = 'Albert'
在内存中的变化如图所示:
??在遍历两个列表各项的值时,明显可以发现,一级列表实现了改操作的独立,但由于没有开辟新的内存空间用以存储子列表,所以子列表的修改操作并没有独立开。
深 Copy
??要想copy得到的新列表与原列表的改操作完全独立开,必须有一种可以区分可变类型和不可变类型的copy机制。这便是深Copy。 对于深Copy操作,必须要导入外部模块,再调用deepcopy() 方法
import copy
list1 = ['tom', 'alex', ['albert', 'abel', 'adam']]
list4 = copy.deepcopy(list1)
??而后,通过打印每个列表id探究原列表和新列表在内存中的存储方式。
print(id(list1), id(list4))
print(id(list1[0]), id(list1[1]), id(list1[2]))
print(id(list1[2][0]), id(list1[2][1]), id(list1[2][2]))
print(id(list4[0]), id(list4[1]), id(list4[2]))
print(id(list4[2][0]), id(list4[2][1]), id(list4[2][2]))
"""
打印结果:
id(list1):2412909307776;id(list4):2412909305984
# 原列表各项的id:
2412908165680 2412908166448 2412909227456
2412907856368 2412909354800 2412909354864
# 新列表各项的id:
2412908165680 2412908166448 2412909308224
2412907856368 2412909354800 2412909354864
"""
??可以简单的画出存储形式:
??从存储形式中可以发现,在内存中新开辟了两块内存空间,用以存储复制产生的新列表,包括子列表。在此时,修改原列表某一项的值。
list1[0] = 'Tom'
list1[2][0] = 'Albert'
在内存中的变化为: ??在遍历两个列表各项的值时,明显可以发现,list1 某项值的改变(包括子列表中某一项的值),不会引起深Copy产生的新列表。也就是说:对于原列表和新列表,针对改操作,两个列表已经完全独立开,完全实现了两个需求。
总结
- 对于浅Copy:如果原列表存储的都是不可变类型,浅copy完全可以实现需求。
- 对于深Copy:如果原列表存储有可变类型和不可变类型,深Copy才可以实现需求
|