【语法篇】深拷贝和浅拷贝在编写Python代码的时候,我们经常在两个变量间通过=号进行链接,这样的好处是两个变量都可以使
在编写Python代码的时候,我们经常在两个变量间通过=
号进行链接,这样的好处是两个变量都可以使用某些内容。例如下面这段代码:
old = [1, 2, 3, 4, 5]
new = old
print("new:", new)
print("old:", old)
这样一来,我们得到了两个包含[1, 2, 3, 4, 5]
的列表,且不论是通过old
变量还是通过new
变量,我们都可以做到操作这个列表,首先,用=
号的操作不能称为拷贝,而是赋值
,它只是将一个变量通过另一个变量绑定在某个对象上。这个时候,通过任何一个变量改变对象时,另外一个变量也一定会改变。
old = [1, 2, 3, 4, 5]
new = old
print("new:", new)
print("old:", old)
old.append(6)
print("new:", new)
print("old:", old)
new: [1, 2, 3, 4, 5]
old: [1, 2, 3, 4, 5]
new: [1, 2, 3, 4, 5, 6]
old: [1, 2, 3, 4, 5, 6]
1. 在内存空间中开辟出一块内存空间,该空间存储[1, 2, 3, 4, 5]这样的一个列表对象(简称对象A)
2. 将变量old与对象A通过一条连线进行绑定(这样我们就可以根据连线,通过old变量找到对象A)
3. 通过old变量找到对象A,然后将变量new通过一条连线实现与对象A的绑定
4. 通过old变量找到对象A,在对象A中添加一个元素6
浅拷贝
拷贝
是指将当前对象重新复制一份,在跟变量进行绑定。
old = [1, 2, 3, 4, 5]
new = old[:]
print("new:", new)
print("old:", old)
old.append(6)
print("new:", new)
print("old:", old)
new: [1, 2, 3, 4, 5]
old: [1, 2, 3, 4, 5]
new: [1, 2, 3, 4, 5]
old: [1, 2, 3, 4, 5, 6]
此时我们可以看出来,对象是被重新制作了一份,然后在跟变量进行绑定的,这个时候,我们更改某个变量的时候,另外一个变量指向的
对象
是不受任何影响的。
但是,如果当我们的对象中存在其他对象时,可能会出现BUG。
old = [1, 2, 3, [4, 5, 6], 7, 8]
new = old[:]
old.append(9)
old[3].append(10)
print("new:", new)
print("old:", old)
new: [1, 2, 3, [4, 5, 6, 10], 7, 8]
old: [1, 2, 3, [4, 5, 6, 10], 7, 8, 9]
可以看到,new
指向的对象中并没有9这个数字,但是却存在10,这就是由于浅拷贝
导致的。
浅拷贝拷贝的只是最外层对象,内部对象仍然是引用的。
通过
[:]
,copy.copy
,for循环
,列表生成式
实现的拷贝都是浅拷贝。
深拷贝
通过迭代的方式,将所有的对象都进行一份拷贝
,通过copy.deepcopy
实现。
import copy
old = [1, 2, 3, [4, 5, 6], 7, 8]
new = copy.deepcopy(old)
old.append(9)
old[3].append(10)
print("new:", new)
print("old:", old)
new: [1, 2, 3, [4, 5, 6], 7, 8]
old: [1, 2, 3, [4, 5, 6, 10], 7, 8, 9]
深拷贝与浅拷贝的优势分析
- 内存分析
可以通过分析得到,浅拷贝更加节省内存,因为没必要构建出所有的新的一份对象
2.安全性
深拷贝更加安全,因为每个对象都是独一份的,在修改任意变量的时候,不必担心会不会影响到其他的变量
3.当对象不可变时
假设一个对象中,存在其他对象,但是其他对象都是不可变的,这个时候,不推荐使用深拷贝,这是因为不可变对象无法新增或删除元素,可以保障不会出现某个变量改变时,对其他变量的改变,同时,浅拷贝可以节省很大一部分内存
转载自:https://juejin.cn/post/7407278157449281562