Python中的浅复制与深复制

 

1. 元组:元组是不可变的有序列表。

1 a= [30,40]
2 tuple_a = (1, 2, a)
3 a[0] = 3
4 tuple_a
5 # >>> (1, 2, [3, 40])        # 元组是不可变的,但是元组中的元素如果是引用(某个对象的地址),引用的对象是可能会改变的。

 

2. copy模块中的copy方法可能可以浅复制一个对象。

浅复制的意思是: (1)创建一个新的对象,(2)将原始对象中找到的子对象插入其中。(如果子对象是引用,则复制引用而不是复制引用的对象)

import copy

a= [30,40]
list_a = [1,2,a]
list_b = copy.copy(list_a)
list_a is list_b                 # 返回False。list_a和list_b是两个不同的对象,copy.copy(list_a)执行了浅复制

tuple_a = (1, 2, a)
tuple_b =copy.copy(tuple_a)
tuple_a is tuple_b                # 返回True。根本没有进行浅复制,copy.copy(tuple_a) 直接返回了tuple_a

为什么copy.copy对于不同的对象有不同的行为? copy.copy会使用对象中定义的__copy__或者copy方法,如果对象没有定义相关方法,就直接返回这个对象。

a= [30,40]
tuple_a = (1, 2, a)
list_a = [1,2,a]
# 通过obj.cpoy()调用对象的__copy__,或copy方法
tuple_a.copy()                        # 报错,因为元组没有copy方法。
list_a.copy()               # 正常执行,因为list有cpoy方法
dir(tuple_a)                # 查看对象的方法,可以进一步验证这一点

 

3. 对一个序列进行切片操作,默认执行的是浅复制。根据上一条,浅复制行为又取决于对象中是否定义了、如何定义浅复制。

a= [30,40]

list_a = [1,2,a]
slice_list_a = list_a[:]          # 等同于: slice_list_a = copy.copy(list_a)。 也等同于: slice_list_a = list(list_a)
list_a is slice_list_a          # False
tuple_a = (1, 2, a)
slice_tuple_a = tuple_a[:]        # 等同于: slice_tuple_a = copy.copy(tuple_a)。也等同于: slice_tuple_a = tuple(tuple_a)
tuple_a is slice_tuple_a        # True

 

4. 深复制

深复制的意思是:(1)创建一个新的对象,(2)递归地将在原始对象里找到的子对象的副本插入其中。

简单说就是:副本和父本的内容一样,但是不会相互影响。

5. 结论

  1. 浅复制和深复制的结果只在复合对象(对象包含引用)才有差别。
  2. 明确要求副本和父本不相互影响,最好进行深复制。
  3. 深复制(copy.deepcopy)和浅复制(copy.copy)都会受对象中定义的相关方法所影响,或者说会根据对象的不同,采取不同的行为。
    a = 1
    b = copy.deepcopy(a)
    a is b   # True。因为python中,多个相同的字面量的对象,都是一个对象。或者说,python只会为一个字面量建立最多一个对象。

     

posted @ 2023-07-25 21:35  沈钩  阅读(38)  评论(0编辑  收藏  举报