在Python中复制嵌套列表

74 投票
5 回答
51470 浏览
提问于 2025-04-15 21:00

我想复制一个二维列表,这样如果我修改一个列表,另一个列表就不会受到影响。

对于一维列表,我只需要这样做:

a = [1, 2]
b = a[:]

现在如果我修改了 ba 就不会被修改。

但是对于二维列表,这种方法就不行了:

a = [[1, 2],[3, 4]]
b = a[:]

如果我修改了 ba 也会被修改。

我该怎么解决这个问题呢?

5 个回答

7

为什么 b = a[:] 对嵌套列表(或者说多维列表)不起作用?

a = [[1, 2],[3, 4]]
b = a[:]

回答: 虽然我们用 slicing[:] 操作来复制列表 a,但里面的子列表仍然指向列表 b 中的子列表。

注意:我们可以用 id() 来检查引用在 Python 中的情况。
让我们通过一个例子来理解。

>>> a = [[1,2],[3,4]]
>>> id(a)
140191407209856    # unique id of a
>>> b=a
>>> id(b)
140191407209856
>>> b=a[:]        # Copying list a to b with slicing
>>> id(b)         
140191407209920   # id of list b changed & is not same as id of list a
>>> id(a[0])      
140191407188544
>>> id(b[0])
140191407188544
>>> id(a[0])==id(b[0])  # id of both a[0] & b[1] is same.
True

所以,切片操作不会改变列表内部对象的引用。 你可以从上面看到,a[0] 的引用和 b[0] 是一样的。
当你把一个二维列表复制到另一个列表时,它添加的是对这个列表的引用,而不是实际的列表。

相反,你可以使用:

  • b = copy.deepcopy(a)
  • b = [item[:] for item in a]
  • b = [item.copy() for item in a]
  • b = [list(item) for item in a]
  • b = [copy.copy(item) for item in a]
  • b = []; b.extend(a)

下面是所有可用复制方法的时间复杂度比较来源

  1. 10.59秒 (105.9微秒/次) - copy.deepcopy(old_list)

  2. 10.16秒 (101.6微秒/次) - 纯 Python Copy() 方法复制类时使用 deepcopy

  3. 1.488秒 (14.88微秒/次) - 纯 Python Copy() 方法不复制类(仅复制字典/列表/元组)

  4. 0.325秒 (3.25微秒/次) - for item in old_list: new_list.append(item)

  5. 0.217秒 (2.17微秒/次) - [i for i in old_list] (一个 列表推导式

  6. 0.186秒 (1.86微秒/次) - copy.copy(old_list)

  7. 0.075秒 (0.75微秒/次) - list(old_list)

  8. 0.053秒 (0.53微秒/次) - new_list = []; new_list.extend(old_list)

  9. 0.039秒 (0.39微秒/次) - old_list[:]列表切片

90

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,尤其是当我们刚开始学习编程的时候。比如,有人可能会在使用某个功能时,发现它没有按照预期工作,这时候就需要去查找原因。

通常,我们可以通过查看文档、搜索网上的资料,或者在像StackOverflow这样的社区提问来找到解决办法。在这些平台上,很多经验丰富的程序员会分享他们的经验和解决方案,这对初学者来说非常有帮助。

记住,遇到问题是学习编程的一部分,重要的是要保持耐心,积极寻找解决方案。随着时间的推移,你会逐渐掌握更多的知识和技能。

b = [x[:] for x in a]
91

如果你想要一个更通用的解决方案,不管数据有多少维度,都可以使用 copy.deepcopy()

import copy
b = copy.deepcopy(a)

撰写回答