Python对象的深浅拷贝,你到底变不变
- 2020 年 4 月 11 日
- 筆記

在Python有个重要的东西,就是对象的深浅拷贝。
我们就称为:'==' vs 'is'
- == 比较对象之间的值是否相等
- is 比较的是对象身份是否相等,它们是否同一个对象
我们一般通过id来是否相等来判断是否同一个对象
a = 10 b = 10 a == b True id(a) 4427562448 id(b) 4427562448 a is b True
注意a is b == True 只适合和用于-5 到256之间,这个不知道你是否知道,我觉得面试官肯定不知道。
a = 257 b = 257 a == b True id(a) 4473417552 id(b) 4473417584 a is b False
下面我们说下,浅拷贝和深拷贝
l1 = [1, 2, 3] l2 = list(l1) l2 [1, 2, 3] l1 == l2 True l1 is l2 False s1 = set([1, 2, 3]) s2 = set(s1) s2 {1, 2, 3} s1 == s2 True s1 is s2 False
浅拷贝指重新分配一块内存,l2 就是l1的浅拷贝,但是只要是序列的浅拷贝,他们的id就是不一样的。
对于深拷贝,在python中提供了对应的函数copy.copy()
import copy l1 = [1, 2, 3] l2 = copy.copy(l1)
t1 = (1, 2, 3) t2 = tuple(t1) t1 == t2 True t1 is t2 True
元组(1,2,3)只被创建一次,t1和t2同时指向这个元组,反正你看到copy.copy()就是两个True
这里有一个天天来骗小孩的东西,就是l1变了,l2变不变的问题
我这里在使用的嵌套列表
l1 = [[1, 2], (30, 40)] l2 = list(l1) l2 [[1, 2], (30, 40)] l1.append(100) l1[0].append(3) l1 [[1, 2, 3], (30, 40), 100] l2 [[1, 2, 3], (30, 40)]
l2竟然变了,这是为什么。首先初始化一个列表l1,里面的元素是一个列表和元组,然后对l1执行浅拷贝,赋予了l2 ,但是l2中的元素和l1指向同一个列表和元组对象,只有列表对象变,你浅拷贝就要跟着我变。
如果你添加一个序列来,我浅拷贝没有指向你新来的对象。我干嘛跟着你变。
l1.append(100)l1的列表新增元素100,不会对l2产生影响,l1和l2是两个不同的对象
如果我在元组加呢???
l1[1] += (50, 60) l1 [[1, 2, 3], (30, 40, 50, 60), 100] l2 [[1, 2, 3], (30, 40)]
竟然不会变,说白了只有列表对象变,难道元组不可变你不知道?
深度拷贝
深度拷贝,就是你爱怎么变,就去哪里变,我就不变了。
import copy l1 = [[1, 2], (30, 40)] l2 = copy.deepcopy(l1) l1.append(100) l1[0].append(3) l1 [[1, 2, 3], (30, 40), 100] l2 [[1, 2], (30, 40)]
因为此时l1和l2完全独立了,没有任何影响
总结起来其实就是两句话
- 浅拷贝,不可变的不可变,可变的依旧可变
- 深拷贝,都不可变