问题:了解dict.copy()-浅还是深?
在阅读的文档时dict.copy()
,它说它制作了该词典的浅表副本。我关注的书(Beazley的Python参考)也是如此,该书说:
m.copy()方法对映射对象中包含的项目进行浅表复制,并将其放置在新的映射对象中。
考虑一下:
>>> 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}
因此,我认为这也将更新original
(并添加’c’:3)的值,因为我正在执行浅表复制。就像您对列表进行操作一样:
>>> original = [1, 2, 3]
>>> new = original
>>> new.append(4)
>>> new, original
([1, 2, 3, 4], [1, 2, 3, 4])
这按预期工作。
由于两者都是浅表副本,为什么为什么dict.copy()
按我的预期无法正常工作?还是我对浅复制和深复制的理解存在缺陷?
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:
The m.copy() method makes a shallow copy of the items contained in a mapping object and places them in a new mapping object.
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 = [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?
回答 0
“浅复制”表示字典的内容不是按值复制,而只是创建一个新引用。
>>> 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]})
相反,深层副本将按值复制所有内容。
>>> 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]})
所以:
b = a
:参考分配,制造a
并b
指向同一对象。
b = a.copy()
:浅拷贝,a
并且b
将成为两个独立的对象,但其内容仍共享相同的参考
b = copy.deepcopy(a)
:深度复制,a
并且b
的结构和内容变得完全孤立。
By “shallow copying” it means the content of 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:
b = a
: Reference assignment, Make a
and b
points to the same object.
b = a.copy()
: Shallow copying, a
and b
will become two isolated objects, but their contents still share the same reference
b = copy.deepcopy(a)
: Deep copying, a
and b
‘s structure and content become completely isolated.
回答 1
这不是深拷贝或浅拷贝的问题,您要做的只是深拷贝。
这里:
>>> new = original
您正在创建对原始引用的列表/字典的新引用。
而在这里:
>>> new = original.copy()
>>> # or
>>> new = list(original) # dict(original)
您正在创建一个新的列表/字典,其中填充了原始容器中包含的对象引用的副本。
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.
回答 2
举个例子:
original = dict(a=1, b=2, c=dict(d=4, e=5))
new = original.copy()
现在,让我们在“浅”(第一)级别中更改一个值:
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
现在让我们将值更深一级地更改:
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
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
回答 3
添加到肯尼的答案。当您进行浅表复制parent.copy()时,会使用相同的键创建一个新字典,但不会复制它们的值。如果将新值添加到parent_copy,则不会影响父对象,因为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]}
parent [1],parent_copy [1]的hash(id)值相同,这意味着存储在id 140690938288400中的parent [1]和parent_copy [1]的 [1,2,3] 。
但是parent和parent_copy的哈希值不同,这意味着它们是不同的字典,并且parent_copy是一个新字典,其值引用了parent的值
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_copy it won’t effect parent because parent_copy is a new dictionary not reference.
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.
But hash of parent and parent_copy are different which implies They are different dictionaries and parent_copy is a new dictionary having values reference to values of parent
回答 4
“ new”和“ original”是不同的dict,这就是为什么您只能更新其中之一。.这些项目是浅复制的,而不是dict本身。
“new” and “original” are different dicts, that’s why you can update just one of them.. The items are shallow-copied, not the dict itself.
回答 5
内容是浅复制的。
所以,如果原来的dict
包含list
或另一个dictionary
,在原或其浅拷贝修改一个他们将修改他们(list
或dict
)在其他。
Contents are shallow copied.
So if the original dict
contains a list
or another dictionary
, modifying one them in the original or its shallow copy will modify them (the list
or the dict
) in the other.
回答 6
在第二部分中,您应该使用 new = original.copy()
.copy
和=
是不同的东西。
In your second part, you should use new = original.copy()
.copy
and =
are different things.
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。