python浅拷贝和深度拷贝

tech2024-03-25  13

总结

先来看浅拷贝。常见的浅拷贝的方法,是使用数据类型本身的构造器,比如下面两个例子: 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

浅拷贝,是指重新分配一块内存,创建一个新的对象,里面的元素是原对象中子对象的引用。因此,如果原对象中的元素不可变,那倒无所谓;但如果元素可变,浅拷贝通常会带来一些副作用,尤其需要注意。我们来看下面的例子:

l1 = [[1, 2], (30, 40)] l2 = list(l1) l1.append(100) l1[0].append(3) l1 [[1, 2, 3], (30, 40), 100] l2 [[1, 2, 3], (30, 40)] l1[1] += (50, 60) l1 [[1, 2, 3], (30, 40, 50, 60), 100] l2 [[1, 2, 3], (30, 40)]

这个例子中,我们首先初始化了一个列表 l1,里面的元素是一个列表和一个元组;然后对 l1 执行浅拷贝,赋予 l2。因为浅拷贝里的元素是对原对象元素的引用,因此 l2 中的元素和 l1 指向同一个列表和元组对象

接着往下看。l1.append(100),表示对 l1 的列表新增元素 100。这个操作不会对 l2 产生任何影响,因为 l2 和 l1 作为整体是两个不同的对象,并不共享内存地址。操作过后 l2 不变,l1 会发生改变

所谓深度拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。Python 中以 copy.deepcopy() 来实现对象的深度拷贝。比如上述例子写成下面的形式,就是深度拷贝: 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)]
总结
比较操作符’=='表示比较对象间的值是否相等,而’is’表示比较对象的标识是否相等,即它们是否指向同一个内存地址。比较操作符’is’效率优于’==’,因为’is’操作符无法被重载,执行’is’操作只是简单的获取对象的 ID,并进行比较;而’= ='操作符则会递归地遍历对象的所有值,并逐一比较。浅拷贝中的元素,是原对象中子对象的引用,因此,如果原对象中的元素是可变的,改变其也会影响拷贝后的对象,存在一定的副作用。深度拷贝则会递归地拷贝原对象中的每一个子对象,因此拷贝后的对象和原对象互不相关。另外,深度拷贝中会维护一个字典,记录已经拷贝的对象及其 ID,来提高效率并防止无限递归的发生
最新回复(0)