python的几种拷贝方式
这些天遇到高手问了我几个python比较有深度的问题:第一个是python的怎么把创建的对象内存给释放掉,本章不做总结,再者就是这个python的拷贝方式,这里总结分为3种,咱们先来说说这个:
我们可以通过id()方法查看当前这个对象储存的物理地址。
1、通过直接赋值的方式
old_list = [1, 2, 3]
new_list = old_list
print(id(old_list), id(new_list))
old_list.append(6)
print(old_list, new_list)
print(id(old_list), id(new_list))
结果输出为:
1530306843208 1530306843208
[1, 2, 3, 6] [1, 2, 3, 6]
1530306843208 1530306843208
可见结果是完全一样的(包括值和地址)
2、浅拷贝:使用copy()
old_list = [1, 2, 3]
new_list2 = old_list.copy()
print(old_list, new_list2)
print(id(old_list), id(new_list2))
old_list.append(6)
new_list2.append("浅拷贝")
print(old_list, new_list2)
print(id(old_list), id(new_list2))
结果输出为:
[1, 2, 3] [1, 2, 3]
2089174717000 2089174717512
[1, 2, 3, 6] [1, 2, 3, '浅拷贝']
2089174717000 2089174717512
可以看出只有最开始的两个列表的值是一样的,其他没有什么联系,改变了某一个列表的值也不会对另一个列表产生影响
(浅拷贝)再看另一个list包含另一个list的情况:
old_list = [1, 2, 3, [4, 5]]
new_list2 = old_list.copy()
print(old_list, new_list2)
print(id(old_list), id(new_list2))
old_list[3][0] = 5
print(old_list, new_list2)
print(id(old_list), id(new_list2))
运行结果为:
[1, 2, 3, [4, 5]] [1, 2, 3, [4, 5]]
2722822378568 2722822943112
[1, 2, 3, [5, 5]] [1, 2, 3, [5, 5]]
2722822378568 2722822943112
代码意思为替换列表中的第四位元素中的第一个元素,可以看到地址都没有变化,但是值都变了,原因是浅拷贝只是拷贝了第四个元素,而不管里面的值。
3、深拷贝:使用copy库中的deepcopy()
包含对象里面的子对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变
import copy
old_list = [1, 2, 3, [4, 5]]
new_list3 = copy.deepcopy(old_list)
print(old_list, new_list3)
print(id(old_list), id(new_list3))
old_list.append(6)
print(old_list, new_list3)
print(id(old_list), id(new_list3))
运行结果为:
[1, 2, 3, [4, 5]] [1, 2, 3, [4, 5]]
2145661532104 2145661482312
[1, 2, 3, [4, 5], 6] [1, 2, 3, [4, 5]]
2145661532104 2145661482312
该部分和浅拷贝一样,因为都对第一层的对象做了拷贝
(深拷贝)再看另一个list包含另一个list的情况:
import copy
old_list = [1, 2, 3, [4, 5]]
new_list3 = copy.deepcopy(old_list)
print(old_list, new_list3)
print(id(old_list), id(new_list3))
old_list[3][0] = 5
print(old_list, new_list3)
print(id(old_list), id(new_list3))
运行结果为:
[1, 2, 3, [4, 5]] [1, 2, 3, [4, 5]]
1208770731400 1208770803784
[1, 2, 3, [5, 5]] [1, 2, 3, [4, 5]]
1208770731400 1208770803784
如图所示,这里没有像浅拷贝(列表对象里面的子对象不会改变)一样,这里就是深拷贝和浅拷贝的区别,深拷贝会把这个列表中的所有对象(如有对象包含子对象,会将子对象也拷贝一份)拷贝一份另存,所以深拷贝比较耗费内存,慎用!