Python 浅拷贝、深拷贝和普通赋值操作有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17246693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between shallow copy, deepcopy and normal assignment operation?
提问by deeshank
import copy
a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}
a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)
print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))
I get the following results:
我得到以下结果:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
If I perform deepcopy:
如果我执行深层复制:
a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)
results are the same:
结果是一样的:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
If I work on assignment operations:
如果我从事分配操作:
a1 = a
b1 = b
c1 = c
d1 = d
then results are:
那么结果是:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True
Can somebody explain what exactly makes a difference between the copies? Is it something related to mutable & immutable objects? If so, can you please explain it to me?
有人可以解释一下副本之间到底有什么不同吗?它与可变和不可变对象有关吗?如果是这样,你能向我解释一下吗?
采纳答案by grc
Normal assignment operations will simply point the new variable towards the existing object. The docsexplain the difference between shallow and deep copies:
正常的赋值操作只会将新变量指向现有对象。该文档解释了浅层和深层副本之间的区别:
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
浅拷贝和深拷贝的区别仅与复合对象(包含其他对象的对象,如列表或类实例)有关:
浅拷贝构造一个新的复合对象,然后(在可能的范围内)向其中插入对原始对象中的对象的引用。
深拷贝构造一个新的复合对象,然后递归地将原始对象中的对象的副本插入其中。
Here's a little demonstration:
这是一个小演示:
import copy
a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]
Using normal assignment operatings to copy:
使用正常的赋值操作来复制:
d = c
print id(c) == id(d) # True - d is the same object as c
print id(c[0]) == id(d[0]) # True - d[0] is the same object as c[0]
Using a shallow copy:
使用浅拷贝:
d = copy.copy(c)
print id(c) == id(d) # False - d is now a new object
print id(c[0]) == id(d[0]) # True - d[0] is the same object as c[0]
Using a deep copy:
使用深拷贝:
d = copy.deepcopy(c)
print id(c) == id(d) # False - d is now a new object
print id(c[0]) == id(d[0]) # False - d[0] is now a new object
回答by perreal
For immutable objects, there is no need for copying because the data will never change, so Python uses the same data; ids are always the same. For mutable objects, since they can potentially change, [shallow] copy creates a new object.
对于不可变对象,不需要复制,因为数据永远不会改变,所以Python使用相同的数据;id 总是相同的。对于可变对象,因为它们可能会改变,[浅] 复制会创建一个新对象。
Deep copy is related to nested structures. If you have list of lists, then deepcopy copiesthe nested lists also, so it is a recursive copy. With just copy, you have a new outer list, but inner lists are references.
深拷贝与嵌套结构有关。如果您有列表列表,那么也深度copies复制嵌套列表,因此它是递归复制。只需复制,您就有了一个新的外部列表,但内部列表是引用。
Assignment does not copy. It simply sets the reference to the old data. So you need copy to create a new list with the same contents.
分配不复制。它只是设置对旧数据的引用。因此,您需要复制以创建具有相同内容的新列表。
回答by Andrew Gorcester
a, b, c, d, a1, b1, c1 and d1 are references to objects in memory, which are uniquely identified by their ids.
a、b、c、d、a1、b1、c1 和 d1 是对内存中对象的引用,它们由它们的 id 唯一标识。
An assignment operation takes a reference to the object in memory and assigns that reference to a new name. c=[1,2,3,4]is an assignment that creates a new list object containing those four integers, and assigns the reference to that object to c. c1=cis an assignment that takes the same reference to the same objectand assigns that to c1. Since the list is mutable, anything that happens to that list will be visible regardless of whether you access it through cor c1, because they both reference the same object.
赋值操作获取对内存中对象的引用,并将该引用分配给一个新名称。 c=[1,2,3,4]是一个赋值,它创建一个包含这四个整数的新列表对象,并将对该对象的引用分配给c。 c1=c是一个赋值,它采用对同一对象的相同引用并将其分配给c1。由于列表是可变的,因此无论您是通过c还是访问该列表,发生在该列表上的任何事情都是可见的c1,因为它们都引用了同一个对象。
c1=copy.copy(c)is a "shallow copy" that creates a new list and assigns the reference to the new list to c1. cstill points to the original list. So, if you modify the list at c1, the list that crefers to will not change.
c1=copy.copy(c)是一个“浅拷贝”,它创建一个新列表并将对新列表的引用分配给c1. c仍然指向原始列表。因此,如果您修改 处c1的列表,则c引用的列表不会改变。
The concept of copying is irrelevant to immutable objects like integers and strings. Since you can't modify those objects, there is never a need to have two copies of the same value in memory at different locations. So integers and strings, and some other objects to which the concept of copying does not apply, are simply reassigned. This is why your examples with aand bresult in identical ids.
复制的概念与不可变对象(如整数和字符串)无关。由于您无法修改这些对象,因此永远不需要在内存中的不同位置拥有相同值的两个副本。因此,整数和字符串,以及复制概念不适用的一些其他对象,只需重新分配即可。这就是为什么您的示例具有a和b导致相同的 ID。
c1=copy.deepcopy(c)is a "deep copy", but it functions the same as a shallow copy in this example. Deep copies differ from shallow copies in that shallow copies will make a new copy of the object itself, but any references insidethat object will not themselves be copied. In your example, your list has only integers inside it (which are immutable), and as previously discussed there is no need to copy those. So the "deep" part of the deep copy does not apply. However, consider this more complex list:
c1=copy.deepcopy(c)是一个“深拷贝”,但它的功能与本示例中的浅拷贝相同。深拷贝与浅拷贝的不同之处在于,浅拷贝将创建对象本身的新副本,但该对象内部的任何引用本身都不会被复制。在您的示例中,您的列表中只有整数(它们是不可变的),并且如前所述,无需复制这些整数。所以深拷贝的“深”部分不适用。但是,请考虑这个更复杂的列表:
e = [[1, 2],[4, 5, 6],[7, 8, 9]]
e = [[1, 2],[4, 5, 6],[7, 8, 9]]
This is a list that contains other lists (you could also describe it as a two-dimensional array).
这是一个包含其他列表的列表(您也可以将其描述为二维数组)。
If you run a "shallow copy" on e, copying it to e1, you will find that the id of the list changes, but each copy of the list contains references to the same three lists -- the lists with integers inside. That means that if you were to do e[0].append(3), then ewould be [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. But e1would also be [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. On the other hand, if you subsequently did e.append([10, 11, 12]), ewould be [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. But e1would still be [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. That's because the outer lists are separate objects that initially each contain three references to three inner lists. If you modify the inner lists, you can see those changes no matter if you are viewing them through one copy or the other. But if you modify one of the outer lists as above, then econtains three references to the original three lists plus one more reference to a new list. And e1still only contains the original three references.
如果在 上运行“浅拷贝” e,将其复制到e1,您会发现列表的 id 发生了变化,但是列表的每个副本都包含对相同的三个列表的引用——里面有整数的列表。这意味着,如果您要这样做e[0].append(3),那么e将会是[[1, 2, 3],[4, 5, 6],[7, 8, 9]]。但e1也会[[1, 2, 3],[4, 5, 6],[7, 8, 9]]。另一方面,如果您随后做了e.append([10, 11, 12]),e将会是[[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]。但e1还是会[[1, 2, 3],[4, 5, 6],[7, 8, 9]]。这是因为外部列表是单独的对象,最初每个对象都包含对三个内部列表的三个引用。如果您修改内部列表,则无论您是通过一个副本还是另一个副本查看这些更改,都可以看到这些更改。但是如果你修改上面的外部列表之一,那么e包含对原始三个列表的三个引用以及对新列表的另一个引用。并且e1仍然只包含原始的三个引用。
A 'deep copy' would not only duplicate the outer list, but it would also go inside the lists and duplicate the inner lists, so that the two resulting objects do not contain any of the same references (as far as mutable objects are concerned). If the inner lists had further lists (or other objects such as dictionaries) inside of them, they too would be duplicated. That's the 'deep' part of the 'deep copy'.
“深拷贝”不仅会复制外部列表,还会进入列表内部并复制内部列表,因此两个结果对象不包含任何相同的引用(就可变对象而言) . 如果内部列表中有更多列表(或其他对象,例如字典),它们也会被复制。那是“深层副本”的“深层”部分。
回答by user1767754
回答by Sohaib Farooqi
For immutable objects, creating a copy don't make much sense since they are not going to change. For mutable objects assignment,copyand deepcopybehaves differently. Lets talk about each of them with examples.
对于不可变对象,创建副本没有多大意义,因为它们不会改变。对于可变对象assignment,copy而deepcopy表现不同。让我们用例子来讨论它们中的每一个。
An assignment operation simply assigns the reference of source to destination e.g:
赋值操作只是将源的引用分配给目标,例如:
>>> i = [1,2,3]
>>> j=i
>>> hex(id(i)), hex(id(j))
>>> ('0x10296f908', '0x10296f908') #Both addresses are identical
Now iand jtechnically refers to same list. Both iand jhave same memory address. Any updation to either
of them will be reflected to the other. e.g:
现在i和j技术上是指相同的列表。双方i并j具有相同的内存地址。对其中任何一个的任何更新都将反映到另一个。例如:
>>> i.append(4)
>>> j
>>> [1,2,3,4] #Destination is updated
>>> j.append(5)
>>> i
>>> [1,2,3,4,5] #Source is updated
On the other hand copyand deepcopycreates a new copy of variable. So now changes to original variable will not be reflected
to the copy variable and vice versa. However copy(shallow copy), don't creates a copy of nested objects, instead it just
copies the reference of nested objects. Deepcopy copies all the nested objects recursively.
另一方面,copy并deepcopy创建变量的新副本。所以现在对原始变量的更改不会反映到复制变量,反之亦然。但是copy(shallow copy),不要创建嵌套对象的副本,而只是复制嵌套对象的引用。Deepcopy 递归复制所有嵌套对象。
Some examples to demonstrate behaviour of copyand deepcopy:
演示copy和行为的一些示例deepcopy:
Flat list example using copy:
平面列表示例使用copy:
>>> import copy
>>> i = [1,2,3]
>>> j = copy.copy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different
>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable
Nested list example using copy:
嵌套列表示例使用copy:
>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.copy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different
>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x10296f908') #Nested lists have same address
>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5,6]] #Updation of original nested list updated the copy as well
Flat list example using deepcopy:
平面列表示例使用deepcopy:
>>> import copy
>>> i = [1,2,3]
>>> j = copy.deepcopy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different
>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable
Nested list example using deepcopy:
嵌套列表示例使用deepcopy:
>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.deepcopy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different
>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x102b9b7c8') #Nested lists have different addresses
>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5]] #Updation of original nested list didn't affected the copied variable
回答by Sandeep
Below code demonstrates the difference between assignment, shallow copy using the copy method, shallow copy using the (slice) [:] and the deepcopy. Below example uses nested lists there by making the differences more evident.
下面的代码演示了赋值、使用 copy 方法的浅拷贝、使用 (slice) [:] 的浅拷贝和深拷贝之间的区别。下面的示例通过使差异更加明显来使用嵌套列表。
from copy import deepcopy
########"List assignment (does not create a copy) ############
l1 = [1,2,3, [4,5,6], [7,8,9]]
l1_assigned = l1
print(l1)
print(l1_assigned)
print(id(l1), id(l1_assigned))
print(id(l1[3]), id(l1_assigned[3]))
print(id(l1[3][0]), id(l1_assigned[3][0]))
l1[3][0] = 100
l1.pop(4)
l1.remove(1)
print(l1)
print(l1_assigned)
print("###################################")
########"List copy using copy method (shallow copy)############
l2 = [1,2,3, [4,5,6], [7,8,9]]
l2_copy = l2.copy()
print(l2)
print(l2_copy)
print(id(l2), id(l2_copy))
print(id(l2[3]), id(l2_copy[3]))
print(id(l2[3][0]), id(l2_copy[3][0]))
l2[3][0] = 100
l2.pop(4)
l2.remove(1)
print(l2)
print(l2_copy)
print("###################################")
########"List copy using slice (shallow copy)############
l3 = [1,2,3, [4,5,6], [7,8,9]]
l3_slice = l3[:]
print(l3)
print(l3_slice)
print(id(l3), id(l3_slice))
print(id(l3[3]), id(l3_slice[3]))
print(id(l3[3][0]), id(l3_slice[3][0]))
l3[3][0] = 100
l3.pop(4)
l3.remove(1)
print(l3)
print(l3_slice)
print("###################################")
########"List copy using deepcopy ############
l4 = [1,2,3, [4,5,6], [7,8,9]]
l4_deep = deepcopy(l4)
print(l4)
print(l4_deep)
print(id(l4), id(l4_deep))
print(id(l4[3]), id(l4_deep[3]))
print(id(l4[3][0]), id(l4_deep[3][0]))
l4[3][0] = 100
l4.pop(4)
l4.remove(1)
print(l4)
print(l4_deep)
print("##########################")
print(l4[2], id(l4[2]))
print(l4_deep[3], id(l4_deep[3]))
print(l4[2][0], id(l4[2][0]))
print(l4_deep[3][0], id(l4_deep[3][0]))
回答by Fouad Boukredine
The GIST to take is this:
Dealing with shallow lists (no sub_lists, just single elements) using "normal assignment" rises a "side effect" when you create a shallow list and then you create a copy of this list using "normal assignment". This "side effect" is when you change any element of the copy list created, because it will automatically change the same elements of the original list. That is when copycomes in handy, as it won't change the original list elements when changing the copy elements.
要采用的 GIST 是这样的:使用“正常分配”处理浅列表(没有子列表,只有单个元素)会在创建浅列表然后使用“正常分配”创建此列表的副本时产生“副作用” . 这种“副作用”是当您更改创建的副本列表的任何元素时,因为它会自动更改原始列表的相同元素。这就是copy派上用场的时候,因为它在更改副本元素时不会更改原始列表元素。
On the other hand, copydoes have a "side effect" as well, when you have a list that has lists in it (sub_lists), and deepcopysolves it. For instance if you create a big list that has nested lists in it (sub_lists), and you create a copy of this big list (the original list). The "side effect" would arise when you modify the sub_lists of the copy list which would automatically modify the sub_lists of the big list. Sometimes (in some projects) you want to keep the big list (your original list) as it is without modification, and all you want is to make a copy of its elements (sub_lists). For that, your solution is to use deepcopywhich will take care of this "side effect" and makes a copy without modifying the original content.
另一方面,copy当您有一个包含列表的列表(sub_lists)并deepcopy解决它时,它也会产生“副作用” 。例如,如果您创建了一个包含嵌套列表的大列表(sub_lists),并且您创建了这个大列表(原始列表)的副本。当您修改副本列表的 sub_lists 时会出现“副作用”,这将自动修改大列表的 sub_lists。有时(在某些项目中)您希望保持大列表(您的原始列表)原样不变,您想要的只是复制其元素(sub_lists)。为此,您的解决方案是使用deepcopy它来处理这种“副作用”并在不修改原始内容的情况下进行复制。
The different behaviors of copyand deep copyoperations concerns only compound objects (ie: objects that contain other objects such as lists).
copy和deep copy操作的不同行为仅涉及复合对象(即:包含其他对象(如列表)的对象)。
Here are the differences illustrated in this simple code example:
以下是此简单代码示例中说明的差异:
First
第一的
let's check how copy(shallow) behaves, by creating an original list and a copy of this list:
让我们copy通过创建原始列表和此列表的副本来检查(浅层)的行为:
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)
Now, let's run some printtests and see how the original list behave compared to its copy list:
现在,让我们运行一些print测试,看看原始列表与其副本列表相比如何:
original_list and copy_list have different addresses
original_list 和 copy_list 有不同的地址
print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
elements of original_list and copy_list have the same addresses
original_list 和 copy_list 的元素具有相同的地址
print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
sub_elements of original_list and copy_list have the same addresses
original_list 和 copy_list 的 sub_elements 具有相同的地址
print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08
modifying original_list elements does NOT modify copy_list elements
修改 original_list 元素不会修改 copy_list 元素
original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
modifying copy_list elements does NOT modify original_list elements
修改 copy_list 元素不会修改 original_list 元素
copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
modifying original_list sub_elements automatically modify copy_list sub_elements
修改 original_list sub_elements 自动修改 copy_list sub_elements
original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]
modifying copy_list sub_elements automatically modify original_list sub_elements
修改copy_list sub_elements 自动修改original_list sub_elements
copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]
Second
第二
let's check how deepcopybehaves, by doing the same thing as we did with copy(creating an original list and a copy of this list):
让我们deepcopy通过做与我们所做的相同的事情来检查行为copy(创建原始列表和此列表的副本):
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)
Now, let's run some printtests and see how the original list behave compared to its copy list:
现在,让我们运行一些print测试,看看原始列表与其副本列表相比如何:
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)
original_list and copy_list have different addresses
original_list 和 copy_list 有不同的地址
print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
elements of original_list and copy_list have the same addresses
original_list 和 copy_list 的元素具有相同的地址
print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
sub_elements of original_list and copy_list have different addresses
original_list 和 copy_list 的 sub_elements 地址不同
print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300
modifying original_list elements does NOT modify copy_list elements
修改 original_list 元素不会修改 copy_list 元素
original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
modifying copy_list elements does NOT modify original_list elements
修改 copy_list 元素不会修改 original_list 元素
copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
modifying original_list sub_elements does NOT modify copy_list sub_elements
修改 original_list sub_elements 不会修改 copy_list sub_elements
original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
modifying copy_list sub_elements does NOT modify original_list sub_elements
修改 copy_list sub_elements 不会修改 original_list sub_elements
copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]
回答by Nitish Chauhan
In python, when we assign objects like list, tuples, dict, etc to another object usually with a ' = ' sign, python creates copy's by reference. That is, let's say we have a list of list like this :
在python中,当我们将列表、元组、字典等对象分配给另一个通常带有“=”符号的对象时,python会通过引用创建副本。也就是说,假设我们有一个像这样的列表:
list1 = [ [ 'a' , 'b' , 'c' ] , [ 'd' , 'e' , 'f' ] ]
and we assign another list to this list like :
我们为这个列表分配另一个列表,如:
list2 = list1
then if we print list2 in python terminal we'll get this :
然后如果我们在 python 终端中打印 list2 我们会得到这个:
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]
Both list1 & list2 are pointing to same memory location, any change to any one them will result in changes visible in both objects, i.e both objects are pointing to same memory location. If we change list1 like this :
list1 和 list2 都指向相同的内存位置,对它们中的任何一个进行任何更改都会导致两个对象中可见的更改,即两个对象都指向相同的内存位置。如果我们像这样更改 list1 :
list1[0][0] = 'x'
list1.append( [ 'g'] )
then both list1 and list2 will be :
那么 list1 和 list2 都将是:
list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g'] ]
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g' ] ]
Now coming to Shallow copy, when two objects are copied via shallow copy, the child object of both parent object refers to same memory location but any further new changes in any of the copied object will be independent to each other. Let's understand this with a small example. Suppose we have this small code snippet :
现在谈到浅拷贝,当通过浅拷贝复制两个对象时,两个父对象的子对象引用相同的内存位置,但任何复制对象中的任何进一步新更改都将相互独立。让我们通过一个小例子来理解这一点。假设我们有这个小代码片段:
import copy
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ] # assigning a list
list2 = copy.copy(list1) # shallow copy is done using copy function of copy module
list1.append ( [ 'g', 'h', 'i'] ) # appending another list to list1
print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]
notice, list2 remains unaffected, but if we make changes to child objects like :
请注意,list2 不受影响,但如果我们对子对象进行更改,例如:
list1[0][0] = 'x'
then both list1 and list2 will get change :
那么 list1 和 list2 都会发生变化:
list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] ]
Now, Deep copyhelps in creating completely isolated objects out of each other. If two objects are copied via Deep Copy then both parent & it's child will be pointing to different memory location. Example :
现在,深度复制有助于创建彼此完全隔离的对象。如果通过 Deep Copy 复制两个对象,那么父对象和它的子对象都将指向不同的内存位置。例子 :
import copy
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ] # assigning a list
list2 = deepcopy.copy(list1) # deep copy is done using deepcopy function of copy module
list1.append ( [ 'g', 'h', 'i'] ) # appending another list to list1
print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]
notice, list2 remains unaffected, but if we make changes to child objects like :
请注意,list2 不受影响,但如果我们对子对象进行更改,例如:
list1[0][0] = 'x'
then also list2 will be unaffected as all the child objects and parent object points to different memory location :
然后 list2 也不会受到影响,因为所有子对象和父对象都指向不同的内存位置:
list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ' ] ]
Hope it helps.
希望能帮助到你。
回答by sudhir tataraju
>>lst=[1,2,3,4,5]
>>a=lst
>>b=lst[:]
>>> b
[1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4, 5]
>>> lst is b
False
>>> lst is a
True
>>> id(lst)
46263192
>>> id(a)
46263192 ------> See here id of a and id of lst is same so its called deep copy and even boolean answer is true
>>> id(b)
46263512 ------> See here id of b and id of lst is not same so its called shallow copy and even boolean answer is false although output looks same.
回答by remort
Not sure if it mentioned above or not, but it's very importable to undestand that .copy() create reference to original object. If you change copied object - you change the original object. .deepcopy() creates new object and does real copying of original object to new one. Changing new deepcopied object doesn't affect original object.
不确定上面是否提到过,但是理解 .copy() 创建对原始对象的引用非常重要。如果您更改复制的对象 - 您更改原始对象。.deepcopy() 创建新对象并将原始对象真正复制到新对象。更改新的深度复制对象不会影响原始对象。
And yes, .deepcopy() copies original object recursively, while .copy() create a reference object to first-level data of original object.
是的, .deepcopy() 递归复制原始对象,而 .copy() 创建一个引用对象到原始对象的第一级数据。
So the copying/referencing difference between .copy() and .deepcopy() is significant.
因此 .copy() 和 .deepcopy() 之间的复制/引用差异很重要。


