首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python浅拷贝和深拷贝

Python浅拷贝和深拷贝
EN

Stack Overflow用户
提问于 2014-11-16 14:44:42
回答 1查看 211关注 0票数 0

我正在尝试执行一个python脚本,这个脚本应该可以说明浅拷贝和深拷贝之间的区别。

据我理解:

  • 浅拷贝:创建一个对象并将其引用到原始的
  • 深度复制:创建一个对象并将原始内容复制到对象中。

以下是我的节目:

代码语言:javascript
复制
a = [1,2,3]

print(id(a), id(a[0]), id(a[1]))

print("Lets check shallow copy first")

a1 = copy.copy(a)
print(id(a1), id(a1[0]), id(a1[1]))
a2 = copy.deepcopy(a)
print(id(a2), id(a2[0]), id(a2[1]))

输出:

代码语言:javascript
复制
steven@steven-Inspiron-3537:~/python-learning$ ./deepshallow.py 
(139854551376528, 31777112, 31777088)
Lets check shallow copy first
(139854551485040, 31777112, 31777088)
(139854551378616, 31777112, 31777088)
EN

回答 1

Stack Overflow用户

发布于 2014-11-16 15:01:33

在这种情况下,由于列表中的元素是小整数,Python有一个内置机制来引用“相同”对象(整数),而不允许对深度复制的列表进行更改,从而导致对其复制的列表进行更改。

下面是一个像您这样的整数的例子:

代码语言:javascript
复制
In [135]: import copy

In [136]: a1 = [1, 2, 3]

In [137]: a2 = copy.copy(a1)

In [138]: a3 = copy.deepcopy(a1)

In [139]: map(id, a1)
Out[139]: [26960216, 26960192, 26960168]

In [140]: map(id, a2)
Out[140]: [26960216, 26960192, 26960168]

In [141]: map(id, a3)
Out[141]: [26960216, 26960192, 26960168]

在这一点上,我们可以看到列表包含整数,所有的id都是相同的。让我们更改深拷贝中的一个元素。

代码语言:javascript
复制
In [142]: a3[0] = 1000

In [143]: map(id, a1)
Out[143]: [26960216, 26960192, 26960168]

In [144]: map(id, a2)
Out[144]: [26960216, 26960192, 26960168]

In [145]: map(id, a3)
Out[145]: [39759800, 26960192, 26960168]

现在,a3为其第一个条目设置了一个新id,而其他列表则保持不变。现在,让我们更改浅拷贝的第一个条目。

代码语言:javascript
复制
In [146]: a2[0] = 1000

In [147]: map(id, a1)
Out[147]: [26960216, 26960192, 26960168]

In [148]: map(id, a2)
Out[148]: [39759200, 26960192, 26960168]

In [149]: map(id, a3)
Out[149]: [39759800, 26960192, 26960168]

注意,对于整数1000 (作为a2a3的第一个条目),有一个不同的id值。

其原因是Python运行时实际上缓存了一些小整数和其他不可变对象,这意味着引用它们的任何地方都是对单个缓存值的引用。

这里是描述它的消息来源

当前实现为-5到256之间的所有整数保留了一个整数对象数组,当在该范围内创建int时,实际上只需要返回对现有对象的引用。因此,应该可以更改1的值。我怀疑Python在这种情况下的行为是未定义的。:-)

为了看到deepcopycopy有着有意义的不同行为的例子,我们需要一些东西,deepcopycopy的递归调用将产生影响--而缓存的小整数不会发生这种情况。

让我们尝试使用列表列表,我们将修改内容,而不是突然更改最顶层的列表元素之一所指的内容:

代码语言:javascript
复制
In [171]: a1 = [[1], [2], [3]]

In [172]: a2 = copy.copy(a1); a3 = copy.deepcopy(a1)

In [173]: a1
Out[173]: [[1], [2], [3]]

In [174]: a2
Out[174]: [[1], [2], [3]]

In [175]: map(id, a1)
Out[175]: [140608561277264, 140608561418040, 140608561277120]

In [176]: map(id, a2)
Out[176]: [140608561277264, 140608561418040, 140608561277120]

In [177]: a2[0][0] = 1000

In [178]: a1
Out[178]: [[1000], [2], [3]]

In [179]: a2
Out[179]: [[1000], [2], [3]]

In [180]: a3
Out[180]: [[1], [2], [3]]

In [181]: a3[1][0] = 1001

In [182]: a1
Out[182]: [[1000], [2], [3]]

In [183]: a2
Out[183]: [[1000], [2], [3]]

In [184]: a3
Out[184]: [[1], [1001], [3]]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26958168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档