为什么整数列表的深层副本在内存中返回相同的整数?

问题描述 投票:17回答:2

我理解浅层复制和深层复制之间的区别,就像我在课堂上学到的那样。但是以下没有意义

import copy

a = [1, 2, 3, 4, 5] 

b = copy.deepcopy(a)

print(a is b)
print(a[0] is b[0])
----------------------------
~Output~
>False
>True
----------------------------

当对象及其组成元素在深层副本中的不同内存位置重新创建时,print(a[0] is b[0])不应该评估为False吗?我正在测试这个,因为我们已经在课堂上讨论了它,但它似乎没有用。

python python-3.x deep-copy
2个回答
13
投票

在另一个答案中建议,这可能是由于Python已经为小整数实现了对象。虽然这是事实,但并不是导致这种行为的原因。

让我们来看看当我们使用更大的整数时会发生什么。

> from copy import deepcopy
> x = 1000
> x is deepcopy(x)
True

如果我们深入研究copy模块,我们发现调用具有原子值的deepcopy会延迟调用函数_deepcopy_atomic

def _deepcopy_atomic(x, memo):
    return x

所以实际发生的是deepcopy不会复制不可变值,而只会返回它。

例如,intfloatstrfunction等就是这种情况。


11
投票

这种行为的原因是Python优化了小整数,因此它们实际上并不在不同的内存位置。看看id1,它们总是一样的:

>>> x = 1
>>> y = 1
>>> id(x)
1353557072
>>> id(y)
1353557072

>>> a = [1, 2, 3, 4, 5]
>>> id(a[0])
1353557072

>>> import copy
>>> b = copy.deepcopy(a)
>>> id(b[0])
1353557072

来自Integer Objects的参考:

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

© www.soinside.com 2019 - 2024. All rights reserved.