📜  Python复制(深层复制和浅层复制)

📅  最后修改于: 2020-04-15 08:30:38             🧑  作者: Mango

在Python中,赋值语句不复制对象,它们在目标和对象之间创建绑定。当我们使用=运算符时,用户认为这会创建一个新对象;好吧,事实并非如此。它仅创建一个共享原始对象引用的新变量。有时,用户想要使用可变对象,以便该用户寻找一种方法来创建这些对象的“真实副本”或“克隆”。或者,有时用户希望用户可以修改其副本,而无需同时自动修改原始副本,因此我们可以创建对象的副本。
有时需要一个副本,因此可以更改一个副本而不更改另一个副本。在Python中,有两种创建副本的方法:

  • 深拷贝
  • 浅拷贝

为了制作这些副本,我们使用copy模块。我们使用copy模块进行浅层和深层复制操作。例如

# 导入复制模块
import copy
# 初始化列表1
li1 = [1, 2, [3,5], 4]
# 使用复制进行浅复制
li2 = copy.copy(li1)
# 使用Deepcopy进行深拷贝
li3 = copy.deepcopy(li1)

在上面的代码中,返回copy()列表的浅表副本,deepcopy()返回列表的深表副本。

深拷贝

深层复制是复制过程以递归方式进行的过程。这意味着首先构造一个新的集合对象,然后以递归方式填充原始对象中找到的子对象的副本。如果是深层复制,则将对象的副本复制到其他对象中。这意味着对对象副本所做的任何更改都不会反映在原始对象中。在Python中,这是使用“ deepcopy() “函数实现的。

# Python代码演示复制操作复制操作
import copy
# 初始化列表1
li1 = [1, 2, [3,5], 4]
# 使用Deepcopy进行深度复制
li2 = copy.deepcopy(li1)
# 列表的原始元素
print ("深度复制之前的原始元素")
for i in range(0,len(li1)):
    print (li1[i],end=" ")
print("\r")
# 向新列表添加和元素
li2[2][0] = 7
# 变化反映在l2中
print ("深度复制后的新元素列表 ")
for i in range(0,len( li1)):
    print (li2[i],end=" ")
print("\r")
# 更改未反映在原始列表中,因为它是深层副本
print ("深度复制后的原始元素")
for i in range(0,len( li1)):
    print (li1[i],end=" ")

输出:

深度复制之前的原始元素
1 2 [3, 5] 4
深度复制后的新元素列表
1 2 [7, 5] 4
深度复制后的原始元素
1 2 [3, 5] 4

在上面的示例中,在列表中所做的更改在其他列表中生效,表明该列表已被深度复制。

浅拷贝

浅表副本意味着构造一个新的集合对象,然后使用对原始对象中子对象的引用来填充它。复制过程不会递归,因此不会创建子对象本身的副本。如果是浅复制,则将对象的引用复制到其他对象中。这意味着对对象副本所做的任何更改都会反映在原始对象中。在Python中,这是使用“ copy() “函数实现的。

# Python代码演示复制操作
import copy
# 初始化列表1
li1 = [1, 2, [3,5], 4]
# 使用浅复制
li2 = copy.copy(li1)
# 列表的原始元素
print ("浅层复制之前的原始元素")
for i in range(0,len(li1)):
    print (li1[i],end=" ")
print("\r")
# 向新列表添加和元素
li2[2][0] = 7
# 检查是否反映了变化
print ("浅层复制后的原始元素")
for i in range(0,len( li1)):
    print (li1[i],end=" ")

输出:

浅层复制之前的原始元素
1 2 [3, 5] 4
浅层复制后的原始元素
1 2 [7, 5] 4

在上面的示例中,列表中所做的更改确实在其他列表中生效,表明该列表是浅表复制。

要点:
浅层复制和深度复制之间的区别仅与复合对象(包含其他对象的对象,如列表或类实例)有关:

  • 浅表副本构造一个新的复合对象,然后(在可能的范围内)将对原始对象中对象的引用插入其中。
  • 深层副本会构造一个新的复合对象,然后递归地将原始对象中发现的对象的副本插入其中。