为什么更新“浅”复制字典不会更新“原始”字典?[重复]

2024-12-20 08:37:00
admin
原创
131
摘要:问题描述:在阅读 的文档时dict.copy(),它说它对字典进行了浅拷贝。我正在阅读的书 (Beazley 的 Python 参考) 也是如此,其中说:m.copy() 方法对映射对象中包含的项目进行浅拷贝并将其放置在新的映射对象中。考虑一下:>>> original = dict(a=1...

问题描述:

在阅读 的文档时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}

所以我假设这会更新 (并添加 'c': 3) 的值original,因为我正在进行浅拷贝。就像你对列表执行此操作一样:

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

一切按预期进行。

既然两者都是浅拷贝,那为什么dict.copy()不能像我预期的那样工作呢?还是我对浅拷贝和深拷贝的理解有误?


解决方案 1:

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

>>> 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]'。](https://i.sstatic.net/4AQC6.png)

  1. b = a.copy():浅复制,ab会成为两个孤立的对象,但是它们的内容仍然共享同一个引用

![b = a.copy()的说明:a指向{1: L},b指向{1: M},L和M都指向[1, 2, 3]。](https://i.sstatic.net/Vtk4m.png)

  1. b = copy.deepcopy(a):深度复制,a使得b的结构与内容完全隔离。

!['b = copy.deepcopy(a)' 的说明:'a' 指向 '{1: L}','L' 指向 '[1, 2, 3]';'b' 指向 '{1: M}','M' 指向 '[1, 2, 3]' 的不同实例。](https://i.sstatic.net/BO4qO.png)

解决方案 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

解决方案 3:

这不是深层复制或浅层复制的问题,您所做的一切都不是深层复制。

这里:

>>> new = original 

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

在这里:

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

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

解决方案 4:

补充一下 kennytm 的回答。当你进行浅拷贝时,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) 值相同,这意味着parent[1]parent_copy[1]的 [1,2,3]存储在 id 140690938288400 处。

但是父级父级副本的哈希值不同,这意味着它们是不同的字典,而父级副本是一个新的字典,其值引用父级的值

解决方案 5:

“新的”和“原始的”是不同的字典,这就是为什么你只能更新其中一个。项目浅复制的,而不是字典本身。

解决方案 6:

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

.copy=是不同的东西。

解决方案 7:

内容是浅复制。

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用