【问题标题】:Copying python lists复制 python 列表
【发布时间】:2013-06-10 09:12:08
【问题描述】:

就在我以为我已经了解 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?与前面的例子有什么不同?

【问题讨论】:

  • 请注意,使用[:] 进行复制有点神秘 - 通常我发现使用list()copy.copy() 会更好,具体取决于上下文。 (当然,正如答案中所指出的,copy.deepcopy() 可能是您想要的)。

标签: python list deep-copy


【解决方案1】:

切片操作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 级副本的扩展方式相同。

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

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

【讨论】:

  • 一个“浅拷贝”!我不知道那个概念。也许您可以稍微编辑一下答案以进一步解释(只需几句话)。
  • @MarcosGonzalez 现在好点了吗?
  • 那么,在第二个例子中,b=a[:] 和 b=a[:][:] 会完全一样吗?
  • 几乎:后者会复制两次 :)。结果是等价的。
【解决方案2】:

试试这个:

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

【讨论】:

    【解决方案3】:

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

    使用列表理解

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

    或copy.deepcopy()

    import copy
    b = copy.deepcopy(a)
    

    【讨论】:

      猜你喜欢
      • 2015-04-25
      • 2013-07-04
      • 2013-07-04
      • 2019-01-08
      • 2011-10-23
      • 2012-01-11
      • 2016-05-25
      相关资源
      最近更新 更多