Python中的copy.deepcopy

一、copy模块和深浅复制

在Python中,对象的赋值实际上是对象的引用,也就是说,两个变量指向同一个对象。而有时候我们希望得到一个新的对象,它与原对象的值相同,但是在内存中却是独立的,这时候就需要使用复制。Python的copy模块提供了两个函数:copy和deepcopy。浅复制会创建一个新对象,但它只是原始对象的一个副本,如果原始对象的某个元素是对象引用,则新的对象的相应元素也是该对象的引用。深复制会递归复制对象及其所有子对象。

二、copy方法的使用

copy方法的作用是返回一个浅复制了原对象的新对象。拿一个列表作为例子:


list1 = [1, 2, [3, 4]]
list2 = list1.copy()

如果我们改变了列表中的一个元素,另一个列表也会被改变。


list2[0] = 5
print(list1, list2)    # [1, 2, [3, 4]], [5, 2, [3, 4]]

但是如果我们改变列表中的嵌套列表的元素,两个列表不会互相影响。


list2[2][0] = 6
print(list1, list2)    # [1, 2, [6, 4]], [5, 2, [6, 4]]

三、deepcopy方法的使用

deepcopy方法的作用是返回一个深复制了原对象的新对象。上面的例子如果我们使用deepcopy:


import copy
list1 = [1, 2, [3, 4]]
list3 = copy.deepcopy(list1)

list3[2][0] = 6
print(list1, list3)    # [1, 2, [3, 4]], [1, 2, [6, 4]]

可以看到,两个列表的所有元素都完全独立,没有互相影响。

四、深浅复制的应用

使用深浅复制可以帮助我们避免修改原始对象,因此特别适用于以下场景:

1.复制不定长的可变列表

以下代码展示了如何复制不定长度的可变列表,这个列表包含了两个子元素:


import copy
list1 = [1, [2, 3], 4]
list2 = copy.copy(list1)
list2[1][0] = 5
print(list1, list2)    # [1, [5, 3], 4], [1, [5, 3], 4]

可以看出,当我们使用浅复制时修改了list2中子列表的元素,list1也会受到影响。解决这个问题的方法是使用deepcopy:


import copy
list1 = [1, [2, 3], 4]
list3 = copy.deepcopy(list1)
list3[1][0] = 5
print(list1, list3)    # [1, [2, 3], 4], [1, [5, 3], 4]

2.复制复合对象

使用深复制可以复制复合对象,这些对象由多个对象组成并且都是可变的。如果我们使用简单的赋值,原对象和新对象仍然会相互影响。以下代码演示了如何使用deepcopy对复合对象进行复制:


import copy
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

joe = Person('Joe', 30)
jane = Person('Jane', 25)
family1 = [joe, jane]
family2 = copy.deepcopy(family1)
family2[0].age = 35
print(family1[0].age, family2[0].age)    # 30, 35

3.删除列表元素

在Python中使用del语句可以删除列表元素,但是如果我们只是使用浅复制,会出现以下问题:


import copy
list1 = [1, 2, [3, 4]]
list2 = list1.copy()
del list2[2][0]
print(list1, list2)    # [1, 2, [4]], [1, 2, [4]]

可以看到,原列表也被修改了,因为del语句只是删除了指向子元素的引用。如果我们使用deepcopy:


import copy
list1 = [1, 2, [3, 4]]
list3 = copy.deepcopy(list1)
del list3[2][0]
print(list1, list3)    # [1, 2, [3, 4]], [1, 2, [4]]

可以看到,原列表没有受到任何影响。

本文链接:https://my.lmcjl.com/post/12439.html

展开阅读全文

4 评论

留下您的评论.