为什么更新“浅复制”字典不会更新“原始”字典?
为什么更新“浅复制”字典不会更新“原始”字典?
在阅读 dict.copy()
的文档时,它说它会创建字典的浅拷贝。同样,我所使用的书(Beazley's Python Reference)也是这么说的:
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()
不像我期望的那样工作呢?或者说我对浅拷贝和深拷贝的理解有误?
为什么更新“浅拷贝”字典不会更新“原始”字典?
当我们在Python中使用赋值操作符“=”时,实际上是将一个新的引用指向了原始字典。这意味着当我们修改新的引用时,原始字典也会相应地被修改。
然而,在使用copy()函数或list()函数创建字典的浅拷贝时,我们实际上是创建了一个新的字典,并将原始字典中的对象的引用复制到新字典中。这意味着当我们修改新字典时,原始字典并不会被修改,因为它们引用的是不同的对象。
所以,问题的出现是因为在赋值操作符“=”和copy()函数或list()函数之间存在差异。如果想要更新“原始”字典,可以使用深拷贝来创建一个完全独立的副本,这样对副本的修改不会影响原始字典。
解决方法是使用深拷贝函数来创建一个完全独立的副本,这样对副本的修改不会影响原始字典。在Python中,可以使用copy模块中的deepcopy()函数来实现深拷贝:
import copy new = copy.deepcopy(original)
通过使用深拷贝,我们可以确保在更新副本时不会影响原始字典,从而解决了这个问题。
为什么更新"浅拷贝"字典不会更新"原始"字典?
问题的原因是,在Python中,字典的copy()方法会创建一个新的字典对象,但是这个新字典对象中的键和值仍然是原始字典中的引用。因此,当我们更新"浅拷贝"字典中的值时,只会改变新字典中对应键的值,而不会改变原始字典中对应键的值。
解决这个问题的方法是使用深拷贝(deep copy)。深拷贝会创建一个全新的字典对象,其中的键和值都是原始字典中的副本,而不是引用。这样,当我们更新深拷贝字典中的值时,不会影响原始字典中的值。
以下是使用深拷贝来解决这个问题的示例代码:
import copy original = dict(a=1, b=2, c=dict(d=4, e=5)) new = copy.deepcopy(original) new['a'] = 10 # new = {'a': 10, 'b': 2, 'c': {'d': 4, 'e': 5}} # original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}} # 原始字典不会改变 new['c']['d'] = 40 # new = {'a': 10, 'b': 2, 'c': {'d': 40, 'e': 5}} # original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}} # 原始字典也不会改变
通过使用深拷贝,我们可以确保更新副本字典的值不会影响原始字典的值。这在需要保留原始数据的同时进行修改时非常有用。
为什么更新“浅拷贝”字典不会更新“原始”字典?
在Python中,字典的浅拷贝并不是通过值进行复制,而是创建一个新的引用。也就是说,浅拷贝只是创建了一个新的对象,但是其内容仍然与原始字典共享引用关系。
例如,我们有一个字典a,其中包含一个键值对为1:[1,2,3]。我们通过浅拷贝将字典a复制给字典b:
>>> a = {1: [1,2,3]} >>> b = a.copy() >>> a, b ({1: [1, 2, 3]}, {1: [1, 2, 3]})
然后,我们向字典a中的列表值添加一个元素4:
>>> a[1].append(4) >>> a, b ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
可以看到,尽管我们只是修改了字典a中的值,但是字典b中的值也发生了变化。这是因为浅拷贝只复制了字典的引用,而不是其内容。
相比之下,深拷贝会通过值复制所有的内容。我们可以使用copy模块中的deepcopy函数来进行深拷贝:
>>> import copy >>> c = copy.deepcopy(a) >>> a, c ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
同样地,我们向字典a中的列表值添加一个元素5:
>>> a[1].append(5) >>> a, c ({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
可以看到,这次字典c的值并没有发生变化。这是因为深拷贝会完全复制字典的结构和内容,使得两个字典完全独立。
总结一下:
1. `b = a`:这是引用赋值,将a和b指向同一个对象。
2. `b = a.copy()`:这是浅拷贝,a和b成为两个独立的对象,但是它们的内容仍然共享同一个引用。
3. `b = copy.deepcopy(a)`:这是深拷贝,a和b的结构和内容完全独立。
所以,为什么更新浅拷贝的字典不会更新原始字典呢?这是因为浅拷贝只是复制了字典的引用,而不是其内容。如果想要更新原始字典,可以使用深拷贝来创建一个完全独立的副本。
解决这个问题的方法就是使用深拷贝来创建一个完全独立的字典副本。这样,即使更新副本中的值,原始字典也不会受到影响。
希望以上内容对你有所帮助!