为什么更新“浅拷贝”字典不更新“原始”字典?

547 投票
7 回答
323899 浏览
提问于 2025-04-16 05:46

在阅读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()的表现却和我预期的不一样呢?或者说我对浅拷贝和深拷贝的理解有问题?

7 个回答

42

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

在这里:

>>> new = original 

你只是创建了一个指向原始列表或字典的新引用。

而在这里:

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

你创建了一个新的列表或字典,这个新列表或字典里面装的是原始容器中对象的引用的副本。

51

来看这个例子:

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
1275

这里说的“浅拷贝”是指字典的内容并不是通过值来复制的,而只是创建了一个新的引用。

>>> 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]})

所以:

  1. b = a:这是引用赋值,让ab指向同一个对象。

    示意图:'a = b':'a'和'b'都指向'{1: L}','L'指向'[1, 2, 3]'。

  2. b = a.copy():这是浅拷贝,ab会变成两个独立的对象,但它们的内容仍然共享同一个引用。

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

  3. b = copy.deepcopy(a):这是深拷贝,ab的结构和内容完全独立。

    示意图:'b = copy.deepcopy(a)':'a'指向'{1: L}','L'指向'[1, 2, 3]';'b'指向'{1: M}','M'指向一个不同的'[1, 2, 3]'实例。

撰写回答