在Python 2.x中理解深复制与浅复制
在Python 2.x中理解深复制与浅复制
我在网上搜索时发现了这3段代码。问题是预测输出并解释原因。
示例1:
x = 42
y = x
x = x + 1
print x
print y
输出示例1:
43
42
示例2:
x = [1, 2, 3]
y = x
x[0] = 4
print x
print y
输出示例2:
[4, 2, 3]
[4, 2, 3]
示例3:
x = ['foo', [1,2,3], 10.4]
y = list(x) # 或者 x[:]
y[0] = 'fooooooo'
y[1][0] = 4
print x
print y
输出示例3:
['foo', [4, 2, 3], 10.4]
['fooooooo', [4, 2, 3], 10.4]
大部分情况下,我了解这是一个关于浅复制和深复制的问题,但我似乎无法理解这个简单的事情。在示例2中的x[0] = 4
处,我理解x
和y
指向同一个对象,因此这个语句中不仅重新定义了x
,还重新定义了y
。但是为什么在示例3中,这个逻辑不同。在y[0] = 'fooooooo'
这一行应该导致x
和y
被重新定义,就像接下来的一行y[1][0] = 4
导致x
和y
同时被重新定义一样。
Understanding Deep vs Shallow Copy in Python 2.x
在Python 2.x中理解深拷贝和浅拷贝
在Python中,我们经常需要复制一个对象,以便在对其进行修改时保留原始对象的副本。然而,Python中的对象复制有两种方式:浅拷贝和深拷贝。本文将介绍浅拷贝和深拷贝之间的区别,并解释为什么会出现这个问题以及如何解决它。
首先,我们来看一个例子:
>>> x = ['foo', [1,2,3], 10.4] >>> y = list(x) # or x[:] >>> z=x >>> id(x) 4354889544 >>> id(y) 4354890184 >>> id(z) 4354889544
在这个例子中,我们创建了一个列表`x`,它包含了一个字符串`'foo'`,一个列表`[1, 2, 3]`和一个浮点数`10.4`。然后,我们使用`list()`函数将`x`复制到`y`,或者使用切片操作符`x[:]`进行复制。最后,我们将`x`赋值给`z`。
接下来,我们对`y`进行修改:
>>> y[0] = 'fooooooo' >>> y[1][0] = 4 >>> y ['fooooooo', [4, 2, 3], 10.4] >>> x ['foo', [4, 2, 3], 10.4] >>> id(x[1]) 4354889672 >>> id(y[1]) 4354889672
我们发现,当我们修改`y`的第一个元素和第二个元素的第一个元素时,`x`也发生了相应的改变。为什么会这样呢?
原因在于,当我们使用`list()`函数进行复制时,它会在新的内存位置创建一个新的对象,但为了节省空间,Python会保留对可变内部对象(如列表)的相同指针。这意味着,`y`中的可变对象仍然与原始列表共享相同的内存位置。
解决这个问题的方法是使用深拷贝。深拷贝会创建一个完全独立的对象,包括所有嵌套对象。这样,在对其中一个对象进行修改时,不会影响其他对象。
在Python中,我们可以使用`copy.deepcopy()`函数来进行深拷贝:
>>> import copy >>> y = copy.deepcopy(x) >>> y[0] = 'fooooooo' >>> y[1][0] = 4 >>> y ['fooooooo', [4, 2, 3], 10.4] >>> x ['foo', [1, 2, 3], 10.4] >>> id(x[1]) 4354889672 >>> id(y[1]) 4354893000
现在,当我们修改`y`时,`x`不再受影响。
浅拷贝在复制对象时只复制对象本身,而不复制嵌套对象。这导致修改一个对象时,另一个对象也会受到影响。
深拷贝在复制对象时创建一个完全独立的对象,包括所有嵌套对象。这样,修改一个对象不会影响其他对象。
为了解决浅拷贝带来的问题,可以使用`copy.deepcopy()`函数进行深拷贝。
希望本文对你理解Python中的深拷贝和浅拷贝有所帮助!