Skip to content

Latest commit

 

History

History
111 lines (74 loc) · 2.68 KB

File metadata and controls

111 lines (74 loc) · 2.68 KB

深浅拷贝

!> 浅拷贝/深拷贝都是针对可变类型数据而言的

  • **浅拷贝(copy):**拷贝父对象,不会拷贝对象的内部的子对象。
  • 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。

一、浅copy

看示例:

# 1、先进行一个普通的copy,然后在l1列表中修改不可变元素,分别查看列表l1和l2的值
>>> l1 = ['a', 'b', 'c', ['d', 'e', 'f']]
>>> l2 = l1.copy()
>>> l1[0] = 'x'
>>> print(l1)
['x', 'b', 'c', ['d', 'e', 'f']]
>>> print(l2)
['a', 'b', 'c', ['d', 'e', 'f']]
# 可以看到列表l1不可变元素的修改并不会影响到copy后的l2的值

# 2、对列表l1的可变元素进行修改,分别查看列表l1和l2的值
>>> l1 = ['a', 'b', 'c', ['d', 'e', 'f']]
>>> l2 = l1.copy()
>>> l1[3].append('g')
>>> print(l1)
['a', 'b', 'c', ['d', 'e', 'f', 'g']]
>>> print(l2)
['a', 'b', 'c', ['d', 'e', 'f', 'g']]
# 可以看到列表l2的值也跟着改变了

# 查看id
>>> print(id(l1[3]))
1860405494016
>>> print(id(l2[3]))
1860405494016
# 可变元素的id值也相同,说明python为了节省内存,浅拷贝直接引用了之前的内存地址

?> 结论:如果l2是l1的浅拷贝对象,则l1内的不可变元素发生了改变,l2不变;如果l1内的可变元素发生了改变,则l2会跟着改变

深copy

看示例

# 1、先进行不可变元素的修改,分别查看列表l1和l2的值
>>> import copy
>>> l1 = ['a', 'b', 'c', ['d', 'e', 'f']]
>>> l2 = copy.deepcopy(l1)
>>> l1[0] = 'x'
>>> print(l1)
['x', 'b', 'c', ['d', 'e', 'f']]
>>> print(l2)
['a', 'b', 'c', ['d', 'e', 'f']]
# 可以看到列表l1不可变元素的修改并不会影响到deepcopy后的l2的值

# 2、对列表l1的可变元素进行修改,分别查看列表l1和l2的值
>>> l1 = ['a', 'b', 'c', ['d', 'e', 'f']]
>>> l2 = copy.deepcopy(l1)
>>> l1[3].append('g')
>>> print(l1)
['a', 'b', 'c', ['d', 'e', 'f', 'g']]
>>> print(l2)
['a', 'b', 'c', ['d', 'e', 'f']]
# 可以看到列表l2的值并没有随着l1的更改而改变

# 查看id
>>> print(id(l1[3]))
2703620230656
>>> print(id(l2[3]))
2703620206720

?> 结论: 如果l2是l1的深拷贝对象,则l1内的不可变元素发生了改变,l2不变;如果l1内的可变元素发生了改变,l2也不会变,即l2永远不会因为l1的变化而变化。

总结

不论是浅拷贝还是深拷贝,不可变类型都是共用的

区别在于,浅拷贝的可变类型会随着被拷贝对象的改变而改变,深拷贝的可变类型并不会改变

小练习题

l1 = [1, 2, 3, 4, ['jason']]
l2 = l1[::]
l1[-1].append(666)
print(l2)

?> l1的值赋值给l2

?> 赋值为浅copy