在 Python 中复制嵌套列表

Posted

技术标签:

【中文标题】在 Python 中复制嵌套列表【英文标题】:Copying nested lists in Python 【发布时间】:2011-02-02 06:25:19 【问题描述】:

我想复制一个二维列表,这样如果我修改一个列表,另一个不会被修改。

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

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

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

但这不适用于二维列表:

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

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

我该如何解决这个问题?

【问题讨论】:

很多时候,当人们使用嵌套列表并需要以这种方式复制它们时,他们真的很想使用numpy 恕我直言,这只是语言中的一个错误。对于应该相同的两种情况,行为是不同的——解释语言的典型行为。如果你有大代码,很难调试 @SerhiiPoklonskyi 不,这不是错误。当您执行b = a[:] 时,您会创建一个新列表b,因此例如a.append([5, 6]) 不会修改b,因为它只会更改a。但是,a[1][0] = 5更改b,因为它更改了b 引用的列表。 @ArtemisFowl 对我不起作用(a[1][0] 也不会修改 b)。即使会,我也不明白这有什么关系。问题是:当您执行a = b.copy() 时,a 成为内存中的一个单独位置:既不是引用也不是指向b 的指针,即它是一个自变量。但是,如果您这样做 a = b.copy() 并且 b 是一个数组,那将不起作用。这怎么可能有任何合乎逻辑的解释?如果b 是一个数组,a = b.copy() 必须创建一个自变量。否则这是一个错误。 p.s.无意无礼,如果我错了,请向我解释 @SerhiiPoklonskyi 我认为您感到困惑的原因是您误解了 Python。 Python 实际上并没有这样的“二维数组”,它只有列表,可以包含其他列表。我将尝试通过一个示例来演示:您将a 定义为a = [[1, 2], [3, 4]]。然后创建a 的副本:b = a.copy。这是一个不同的列表,但它包含相同的“子列表”,这意味着更改b,例如b.append([5, 6]) 不会更改a,但是更改b 中的列表,例如b[0].append(3)还将更改a 的第一个列表。 【参考方案1】:
b = [x[:] for x in a]

【讨论】:

适当时+1。我个人喜欢避免复制/深度复制(在现实生活中很少有有效的用例;对于超过 2 维 imo 的列表也可以这样说) 你能提供一个用例吗?我正在尝试复制 2D 列表,但我不确定用您提供的变量名称替换什么。 @JohnLocke b 是新列表,a 是旧列表。 x 内部使用。 对我来说,path 是一个二维数组,我想复制 path[i] 所以我做了curr_level = [x[:] for x in path[i]] 这就是我所说的高效(和聪明)编程! (导入额外的模块来做一些没有它们就可以完成的事情是低效的。)【参考方案2】:

对于更通用的解决方案,无论维度数量如何,请使用copy.deepcopy()

import copy
b = copy.deepcopy(a)

【讨论】:

@Dav,你的观点很有道理。我更喜欢总是导入模块以避免名称冲突,而不是逐个处理函数。 :) 请注意,这也会对列表中的实际元素进行深度复制。 @Dav,我不同意,通常最好使用 module.function() 格式。 “命名空间是一个很棒的主意——让我们做更多这样的事!” @FogleBird:但是,PEP-8 实际上似乎暗示from ... import ... 是规范,除非存在命名空间冲突:python.org/dev/peps/pep-0008(参见“Imports”)。

以上是关于在 Python 中复制嵌套列表的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 2 中,无论列表的内容如何,​​如何按值而不是引用复制复杂嵌套元素的列表

Python中嵌套列表增加元素小结

Python基础:列表的深浅复制

使用 Python 语义对 R 中的嵌套列表进行排序

python中flat将嵌套列表中的元素按顺序排列在一个列表中

5——深浅复制bytes和bytearraylinux用户