Python 理解 dict.copy() - 浅还是深?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3975376/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 13:38:37  来源:igfitidea点击:

Understanding dict.copy() - shallow or deep?

pythondictionarycopy

提问by user225312

While reading up the documentation for dict.copy(), it says that it makes a shallow copy of the dictionary. Same goes for the book I am following (Beazley's Python Reference), which says:

在阅读 的文档时dict.copy(),它说它制作了字典的浅拷贝。我正在关注的书(Beazley 的 Python 参考)也是如此,其中说:

The m.copy() method makes a shallow copy of the items contained in a mapping object and places them in a new mapping object.

m.copy() 方法制作映射对象中包含的项目的浅拷贝,并将它们放置在新的映射对象中。

Consider this:

考虑一下:

>>> original = dict(a=1, b=2)
>>> new = original.copy()
>>> new.update({'c': 3})
>>> original
{'a': 1, 'b': 2}
>>> new
{'a': 1, 'c': 3, 'b': 2}

So I assumed this would update the value of original(and add 'c': 3) also since I was doing a shallow copy. Like if you do it for a list:

所以我认为这也会更新original(并添加 'c': 3)的值,因为我正在做一个浅拷贝。就像你为一个列表做的一样:

>>> original = [1, 2, 3]
>>> new = original
>>> new.append(4)
>>> new, original
([1, 2, 3, 4], [1, 2, 3, 4])

This works as expected.

这按预期工作。

Since both are shallow copies, why is that the dict.copy()doesn't work as I expect it to? Or my understanding of shallow vs deep copying is flawed?

由于两者都是浅拷贝,为什么dict.copy()不能像我期望的那样工作?或者我对浅拷贝和深拷贝的理解有缺陷?

采纳答案by kennytm

By "shallow copying" it means the contentof the dictionary is not copied by value, but just creating a new reference.

“浅复制”意味着字典的内容不是按值复制的,而只是创建一个新的引用。

>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> a, b
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].append(4)
>>> a, b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})

In contrast, a deep copy will copy all contents by value.

相比之下,深拷贝将按值复制所有内容。

>>> import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})

So:

所以:

  1. b = a: Reference assignment, Make aand bpoints to the same object.

    Illustration of 'a = b': 'a' and 'b' both point to '{1: L}', 'L' points to '[1, 2, 3]'.

  2. b = a.copy(): Shallow copying, aand bwill become two isolated objects, but their contents still share the same reference

    Illustration of 'b = a.copy()': 'a' points to '{1: L}', 'b' points to '{1: M}', 'L' and 'M' both point to '[1, 2, 3]'.

  3. b = copy.deepcopy(a): Deep copying, aand b's structure and content become completely isolated.

    Illustration of 'b = copy.deepcopy(a)': 'a' points to '{1: L}', 'L' points to '[1, 2, 3]'; 'b' points to '{1: M}', 'M' points to a different instance of '[1, 2, 3]'.

  1. b = a: 引用赋值,Makeab指向同一个对象。

    'a = b' 的说明:'a' 和 'b' 都指向 '{1: L}','L' 指向 '[1, 2, 3]'。

  2. b = a.copy():浅拷贝,a并且b将成为两个独立的对象,但其内容仍共享相同的参考

    'b = a.copy()'的说明:'a'指向'{1: L}','b'指向'{1: M}','L'和'M'都指向'[ 1, 2, 3]'。

  3. b = copy.deepcopy(a): 深拷贝,ab的结构和内容变得完全隔离。

    Illustration of 'b = copy.deepcopy(a)': 'a' points to '{1: L}', 'L' points to '[1, 2, 3]'; 'b' points to '{1: M}', 'M' points to a different instance of '[1, 2, 3]'.

回答by Joril

"new" and "original" are different dicts, that's why you can update just one of them.. The itemsare shallow-copied, not the dict itself.

“new”和“original”是不同的dicts,这就是为什么你只能更新其中一个。这些项目是浅拷贝的,而不是dict本身。

回答by Jungle Hunter

Contentsare shallow copied.

内容是浅复制的。

So if the original dictcontains a listor another dictionary, modifying one them in the original or its shallow copy will modify them (the listor the dict) in the other.

因此,如果原始文件dict包含 alist或另一个dictionary,则在原始文件或其浅表副本中修改它们之一将修改另一个中的它们(thelist或 the dict)。

回答by eumiro

Take this example:

拿这个例子:

original = dict(a=1, b=2, c=dict(d=4, e=5))
new = original.copy()

Now let's change a value in the 'shallow' (first) level:

现在让我们更改“浅”(第一)级别中的值:

new['a'] = 10
# new = {'a': 10, 'b': 2, 'c': {'d': 4, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}}
# no change in original, since ['a'] is an immutable integer

Now let's change a value one level deeper:

现在让我们更深一层地改变一个值:

new['c']['d'] = 40
# new = {'a': 10, 'b': 2, 'c': {'d': 40, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 40, 'e': 5}}
# new['c'] points to the same original['d'] mutable dictionary, so it will be changed

回答by Lie Ryan

It's not a matter of deep copy or shallow copy, none of what you're doing is deep copy.

这不是深拷贝或浅拷贝的问题,你所做的都不是深拷贝。

Here:

这里:

>>> new = original 

you're creating a new reference to the the list/dict referenced by original.

您正在创建对原始引用的列表/字典的新引用。

while here:

在这里:

>>> new = original.copy()
>>> # or
>>> new = list(original) # dict(original)

you're creating a new list/dict which is filled with a copy of the references of objects contained in the original container.

您正在创建一个新的列表/字典,其中填充了原始容器中包含的对象引用的副本。

回答by Vkreddy Komatireddy

Adding to kennytm's answer. When you do a shallow copy parent.copy()a new dictionary is created with same keys,but the values are not copied they are referenced.If you add a new value to parent_copyit won't effect parentbecause parent_copyis a new dictionary not reference.

添加到 kennytm 的答案中。当您执行浅复制parent.copy() 时,会创建一个具有相同键的新字典,但不会复制值,它们会被引用。如果向parent_copy添加新值,则不会影响parent,因为parent_copy是新字典不参考。

parent = {1: [1,2,3]}
parent_copy = parent.copy()
parent_reference = parent

print id(parent),id(parent_copy),id(parent_reference)
#140690938288400 140690938290536 140690938288400

print id(parent[1]),id(parent_copy[1]),id(parent_reference[1])
#140690938137128 140690938137128 140690938137128

parent_copy[1].append(4)
parent_copy[2] = ['new']

print parent, parent_copy, parent_reference
#{1: [1, 2, 3, 4]} {1: [1, 2, 3, 4], 2: ['new']} {1: [1, 2, 3, 4]}

The hash(id) value of parent[1], parent_copy[1]are identical which implies [1,2,3] of parent[1]and parent_copy[1]stored at id 140690938288400.

parent[1]parent_copy[1]的 hash(id) 值是相同的,这意味着parent[1] 的[1,2,3 ]parent_copy[1]存储在 id 140690938288400。

But hash of parentand parent_copyare different which implies They are different dictionaries and parent_copyis a new dictionary having values reference to values of parent

但是parentparent_copy 的哈希值不同,这意味着它们是不同的字典,并且parent_copy是一个新字典,其值引用了parent 的

回答by u9633554

In your second part, you should use new = original.copy()

在你的第二部分,你应该使用 new = original.copy()

.copyand =are different things.

.copy并且=是不同的东西。