【问题标题】:Shallow copy of list[:]list[:] 的浅拷贝
【发布时间】:2019-04-16 07:42:53
【问题描述】:

据此Official Documentation

list[:]

通过浅拷贝创建一个新列表。我进行了以下实验:

>>> squares = [1, 4, 9, 16, 25]
>>> new_squares = square[:]
>>> squares is new_squares
False
>>> squares[0] is new_squares[0]
True
>>> id(squares)
4468706952
>>> id(new_squares)
4468425032
>>> id(squares[0])
4466081856
>>> id(new_squares[0])
4466081856

这里的一切看起来都不错! new_square 和 square 是不同的对象(这里列出),但由于浅拷贝,它们共享相同的内容。但是,下面的结果让我很困惑:

>>> new_squares[0] = 0
>>> new_squares
[0, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]

我更新了 new_square[0] 但 square 不受影响。我检查了他们的身份证:

>>> id(new_squares[0])
4466081824
>>> id(squares[0])
4466081856

可以发现 squares[0] 的 id 没有变化,但是 new_squares[0] 的 id 发生了变化。这和我之前理解的浅拷贝有很大的不同。

谁能解释一下?谢谢!

【问题讨论】:

  • 它是浅的,不是零深度的。如果更新一个变量会改变另一个变量,那么它们根本就不会是副本。
  • 整数是不可变的。试试squares = [[1], 4, 9, 16, 25]; new_squares = squares[:]; new_squares[0].append(2); print(squares[0])

标签: python copy


【解决方案1】:

您有一个表示其他对象容器的列表对象。当您进行浅拷贝时,您会创建一个新的列表对象(如您所见),其中包含对原始列表所包含的相同对象的引用。

new_squares[0] = 0 是一个分配。你说的是“在列表的第 0 个索引处设置一个 新对象”。好吧,列表现在是单独的对象,并且您正在完全替换保存在副本索引处的对象。第 0 个索引处的对象是否可变也没关系,因为您只是替换 list 对象持有的引用。

如果列表包含一个可变对象,并且您要就地修改该对象而不完全更改存储在该索引中的对象,那么您会看到两个列表之间的更改。不是因为列表以任何方式链接,而是因为它们包含对您现在已更改的可变对象的引用。

这可以在下面进行说明,我可以分别对浅拷贝列表进行修改,并导致可变对象在两个列表之间发生变化,即使该可变对象现在位于两者之间的不同索引处。

# MAKING A CHANGE TO THE LIST
a = [1, {'c': 'd'}, 3, 4]
b = a[:]
b.insert(0, 0)

print(a)
print(b)
print()

# MODIFYING A MUTABLE OBJECT INSIDE THE LIST
a[1]['c'] = 'something_else'

print(a)
print(b)

【讨论】:

    【解决方案2】:

    列表是可变的,整数是不可变的

    当你这样做时:

    squares = [1, 4, 9, 16, 25]
    new_squares = square[:]
    

    squares 和 new_squares 有不同的 id

    如果你这样做:

    [id(squares[i]) for i in range(len(squares))]
    [id(new_squares[i]) for i in range(len(new_squares))]
    

    您将看到每个整数的相同 id。 如果你用另一个值修改一个整数,你将拥有这个整数的新 id

    【讨论】:

    • 你说的是真的,但是 Python 解释器有一个内置的从 -5 到 256 的小整数缓存,为了提高效率,所以当你想要一个小整数时,它不需要构建一。所以你的例子并不能完全说明你在说什么。但是更改存储的整数,使它们超出该范围,那么就有可能获得 2 个或更多具有相同值的不同 int 对象(即具有不同 id)。
    猜你喜欢
    • 2012-04-12
    • 2015-01-13
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多