我正在玩python中的浅拷贝。我遇到了一个我没想到的陷阱。
我的假设是浅拷贝是一个类的新实例,它引用了类中的对象。此行为如下所示。
>>> a = { 'a': 1, 'b':2, 'c': [[1,2],2,3,4,5,6] }
>>> c = copy.copy(a['c'])
>>> d = a['c']
>>> a['c'] is c
False
>>> a['c'][0] is c[0]
True
>>> a['c'] is d
True
>>> a['c'][0] is d[0]
True
令我惊讶的是以下内容。由于浅复制列表的元素是a
列表中元素的引用,我假设当我更改了可变第1个元素时,它也会在a
中更改。
>>> c[0] = [3,3]
>>> c
[[3, 3], 2, 3, 4, 5, 6]
>>> a
{'a': 1, 'c': [[1, 2], 2, 3, 4, 5, 6], 'b': 2}
>>> a['c'][0] is c[0]
False
我发现自更改以来,第一个元素不再是a
的引用。
如果我更改了列表中的所有元素,它是否类似于深度复制?
答案 0 :(得分:4)
由于浅复制列表的元素是对'a'列表中元素的引用,我在更改可变第1个元素时假设它也会在'a'中改变。
c
的第一个元素是一个可变的列表。所以,如果你实际做了变异,那么结果将在a
中显示出来。例如:
>>> a = { 'a': 1, 'b':2, 'c': [[1],2,3,4,5,6] }
>>> c = copy.copy(a['c'])
>>> c[0].append(0)
>>> a
{'a': 1, 'b':2, 'c': [[1, 0], 2, 3, 4, 5, 6]}
但你没有改变它;你只需用不同的值替换它。
原始值([1, 2]
)和新值([3, 3]
)都是可变的这一事实无关紧要;你没有改变任何东西(当然除了c
之外......)c
正如你所知,是a['c']
的浅层副本,而不是同一个对象。
所以:
如果我更改了列表中的所有元素,它是否类似于深度复制?
不,有两个方面。更改共享元素意味着您正在更改所有引用。 替换列表中的所有元素将“类似于深度复制”...但不是相同的,除非您用deepcopy
替换它们 - 就像原件的副本一样。如果用浅拷贝替换它们,则只能将完全相同的问题向下推一级。例如:
>>> a = [[[0]]]
>>> b = copy.copy(a[0])
>>> b[0] = copy.copy(b[0])
>>> a[0] is b
False
>>> a[0][0] is b[0]
False
>>> a[0][0][0] is b[0][0]
True
(在你的例子中,你用完全不同的和不相关的值替换它们,这根本不像副本......但我想我知道你的意思。)