创建重复 N 次的可变项目列表

Creating a list of mutable items repeated N times

我有一个包含一组 x 可变项的列表。我想创建另一个列表,其中 x 组可变项重复 n 次。但是,这些项目必须是对唯一对象的引用,而不是简单地对原始对象的引用。

例如,设a = [[1],[2],[3]]。假设我希望里面的数字重复 n=3 次,即 [[0],[2],[3],[1],[2],[3],[1],[2],[3]].

我可以使用 a * 3 轻松做到这一点。问题是,如果我更改 a[0][0] = 0,那么我将得到 a == [[0],[2],[3],[0],[2],[3],[0],[2],[3]],这是不可取的,因为我只想更改第一个元素。还有其他方法可以实现吗?

就这样:

n = [sub_a.copy() for sub_a in a] * 3

你需要 copy() 来避免这个问题。

a = [[1],[2],[3]]

n = [sub_a.copy() for sub_a in a] * 3

a[0] = [-1]
a[2][0] = -1

print (n)

输出:

[[1], [2], [3], [1], [2], [3], [1], [2], [3]]

我刚刚发现我可以通过以下方式做到这一点:

from copy import deepcopy
a = [[1],[2],[3]]
n = 3
b = [deepcopy(val) for _ in range(n) for val in a]

现在如果我设置 b[0][0] = 0,我将得到 b == [[0],[2],[3],[1],[2],[3],[1],[2],[3]]

itertools 有一个名为 repeat. Just pair it with chain 的方法。

from itertools import repeat, chain

a = [1,2,3]

b = list(chain(*repeat(a, 3)))

>>> b
[1,2,3,1,2,3,1,2,3]
a = [1,2,3]
a = a*3  
a[0] =0
print(a)

要获取可变对象的新实例,您可以将对象类型的 copy() 方法映射到相乘列表:

a  = [{1},{2},{3}]
b  = [*map(set.copy,a*3)]

a[0].add(7)
b[0].add(8)
b[3].add(9)
print(a) # [{1, 7}, {2}, {3}]
print(b) # [{8, 1}, {2}, {3}, {1, 9}, {2}, {3}, {1}, {2}, {3}]

如果你不知道项目的类型,或者它们有不同的类型,你可以在列表理解中做到:

b = [ i.copy() for i in a*3 ]

如果不是所有的项目都是可变的,你可以这样做:

b = [type(i)(i) for i in a*3]

如果有些可以None ...

b = [i if i is None else type(i)(i) for i in a*3]

您还可以使用涵盖所有这些情况的 deepcopy,包括包含嵌套对象的对象...

from copy import deepcopy
b  = [*map(deepcopy,a*3)]

非常简单,您需要复制 a,而不是重复引用原始的可变对象。如果你只需要一层复制,你可以这样做,注意它是一个 shallow 复制(见第二个输出)。

a = [[1, 1], [2], [3, 3, 3]]
b = a[:] * 3
b[0] = "change"
print(b)
b[2][1] = "deep"
print(b)

输出:

['change', [2], [3, 3, 3], [1, 1], [2], [3, 3, 3], [1, 1], [2], [3, 3, 3]]
['change', [2], [3, 'deep', 3], [1, 1], [2], [3, 'deep', 3], [1, 1], [2], [3, 'deep', 3]]

看看如何只给第一层一个新的参考。当您尝试更改更深的元素时,您会发现嵌套列表仍然是同一个对象。要修复 那个 问题,请对 b 的每个元素使用深拷贝:

import copy

a = [[1, 1], [2], [3, 3, 3]]
b = [copy.deepcopy(a) for _ in range(3)]
b[0] = "change"
print(b)
b[2][1] = "deep"
print(b)

输出:

['change', [[1, 1], [2], [3, 3, 3]], [[1, 1], [2], [3, 3, 3]]]
['change', [[1, 1], [2], [3, 3, 3]], [[1, 1], 'deep', [3, 3, 3]]]