在Python 2.x中理解深复制与浅复制

8 浏览
0 Comments

在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处,我理解xy指向同一个对象,因此这个语句中不仅重新定义了x,还重新定义了y。但是为什么在示例3中,这个逻辑不同。在y[0] = 'fooooooo'这一行应该导致xy被重新定义,就像接下来的一行y[1][0] = 4导致xy同时被重新定义一样。

0
0 Comments

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中的深拷贝和浅拷贝有所帮助!

0