9

就在我以为我已经理解 Python 列表是如何工作的时候......

>>> a = [1,2,3]
>>> b = a[:]
>>> b
[1,2,3]
>>> b[1]=100
>>> b
[1,100,3]
>>> a
[1,2,3]

到目前为止,一切都很好。我正在用 a 的内容初始化 b,以便 b 指向不同的对象。因此,b 的变化不会影响 a。

现在看看另一个例子:

>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = a[:][:]
>>> b
[[1,2,3],[4,5,6],[7,8,9]]
>>> b[1][1] = 100
>>> b
[[1,2,3],[4,100,6],[7,8,9]]
>>> a
[[1,2,3],[4,100,6],[7,8,9]]

为什么这次b的变化影响了a?与前面的例子有什么不同?

4

3 回答 3

11

切片操作x[:]生成浅拷贝。这意味着,外部列表不同,但包含完全相同的元素。假设a = [[1]]

b = a[:] # is the same as:
b = [x for x in a]

>>> a[0] is b[0]
True

双重切片 ( [:][:]) 仅此而已 - 再次:

b = a[:][:] # is the same as:
b = [y for y in [x for x in a]]

>>> a[0] is b[0]
True

浅拷贝的浅拷贝就是浅拷贝。

所以b仍然是一个浅拷贝a——这些列表是不同的对象,但它们包含相同的元素。然后你改变 中的内部列表b,但它与 中的列表相同a

2级浅拷贝可以用b=[x[:] for x in a]. 它对 n 级副本的扩展方式相同。

顺便说一句,术语“浅拷贝”对于任何类或容器具有相同的含义。

如果你想要真正的深拷贝,你应该考虑使用深拷贝

于 2013-06-13T20:23:45.117 回答
4

silcing [:] 进行浅拷贝。但是内部对象仍然不会被复制,因此如果它们是可变的并且您将修改它们,它们将被修改;)并且在两个列表中您都会看到这个

使用列表理解

b = [i[:] for i in a]

或 copy.deepcopy()

import copy
b = copy.deepcopy(a)
于 2013-06-13T20:27:55.310 回答
1

尝试这个:

In [38]: import copy

In [39]: a = [[1,2,3],[4,5,6],[7,8,9]]

In [40]: b=copy.deepcopy(a)

In [41]: b[1][1] = 100

In [42]: a
Out[42]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [43]: b
Out[43]: [[1, 2, 3], [4, 100, 6], [7, 8, 9]]

阅读更多@ http://docs.python.org/2/library/copy.html

于 2013-06-13T20:29:13.407 回答