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

Python 创建重复N次的可变项列表,python,list-comprehension,multiplication,replicate,Python,List Comprehension,Multiplication,Replicate,我有一个包含一组x可变项的列表。我想创建另一个列表,其中x可变项集重复n次。但是,项目必须是对唯一对象的引用,而不仅仅是对原始对象的引用 例如,让a=[[1]、[2]、[3]]。假设我希望里面的数字被重复n=3次,即[[0]、[2]、[3]、[1]、[2]、[3]、[1]、[2]、[3]、[1]、[2]、[3] 通过使用a*3,我可以很容易地做到这一点。问题是,如果我更改a[0][0]=0,那么我将得到a=[[0]、[2]、[3]、[0]、[2]、[3]、[0]、[2]、[3],这是不可取的,因

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

例如,让
a=[[1]、[2]、[3]]
。假设我希望里面的数字被重复
n=3次,即
[[0]、[2]、[3]、[1]、[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]]
['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]]
['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]]]
只要做:

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]]
['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]]
['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]]]

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

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]

我刚刚发现我可以通过以下方式来实现:

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
有一个方法可以调用。只要把它配上



itertools
为此调用了一个方法。只要把它配上



要获取可变对象的新实例,可以将对象类型的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]
如果有的可以是空的

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)]

要获取可变对象的新实例,可以将对象类型的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]
如果有的可以是空的

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)]

非常简单,您需要复制一个
,而不是重复引用原始的可变对象。如果您只需要一个级别的拷贝,您可以这样做,注意它是浅拷贝(请参见第二个输出)

输出:

[[1], [2], [3], [1], [2], [3], [1], [2], [3]]
['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]]
['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]]]
查看如何仅为第一个级别提供新引用。当您尝试更改更深的元素时,您会看到嵌套列表仍然是同一个对象。要解决该问题,请为
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)
输出:

[[1], [2], [3], [1], [2], [3], [1], [2], [3]]
['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]]
['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]]]

非常简单,您需要复制一个,而不是重复引用原始的可变对象。如果您只需要一个级别的拷贝,您可以这样做,注意它是浅拷贝(请参见第二个输出)

输出:

[[1], [2], [3], [1], [2], [3], [1], [2], [3]]
['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]]
['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]]]
查看如何仅为第一个级别提供新引用。当您尝试更改更深的元素时,您会看到嵌套列表仍然是同一个对象。要解决该问题,请为
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)
输出:

[[1], [2], [3], [1], [2], [3], [1], [2], [3]]
['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]]
['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]]]


似乎
b[0]=1
已将其设置为0:-)@synthesis:“下面”或“上面”这样的术语在可以更改订单的网站上是个坏主意。修复了我的答案。@paxdiablo对我来说一定太晚了。
b[0]=1
似乎已将其设置为0:-)@synthesis:类似“下面”或“上面”这样的术语在一个可以更改顺序的网站上,这是一个坏主意。修复了我的答案。@paxdiablo well对我来说肯定太晚了,因为这只会创建对同一基础副本的三个引用,实际上什么都没有更改。它确实。。。见我的编辑谢谢。我想
copy()
会根据当前的情况创建一个浅拷贝。你是说
deepcopy()
?嗯,我编辑的确切术语可能是错的。copy()足够做您想做的事情,因为我认为deepcopy()应该也足够了。当然,您的代码“有效”,因为
a
是一个整数列表。整数是不可变的。OP专门询问了一组可变对象。使用列表列表尝试此操作。这只会创建对同一基础副本的三个引用,实际上不会更改任何内容。确实如此。。。见我的编辑谢谢。我想
copy()
会根据当前的情况创建一个浅拷贝。你是说
deepcopy()
?嗯,我编辑的确切术语可能是错的。copy()足够做您想做的事情,因为我认为deepcopy()应该也足够了。当然,您的代码“有效”,因为
a
是一个整数列表。整数是不可变的。OP专门询问了一组可变对象。用一个列表试试这个。只是一些学究:
1
是不可变的,尽管
[1]
是可变的。当您执行
lst[idx]=val
时所做的更改是
lst[idx]
的绑定被更改,绑定引用的原始值保持不变。一旦你摸索了基本的绑定/不变性概念,你的Python技能就会达到一个新的水平。@paxdiablo。好的,我编辑了我的问题以备将来参考。只是一些学究:
1
是不可变的,尽管
[1]
是可变的。当您执行
lst[idx]=val
时所做的更改是
lst[idx]
的绑定被更改,绑定引用的原始值保持不变。一旦你摸索了基本的绑定/不变性概念,你的Python技能就会达到一个新的水平。@paxdiablo。好的,我编辑了我的问题以备将来参考。这不是给了
[[1,2,3],[1,2,3],[1,2,3]]
?谢谢!我编辑了我的回答,这不是我的回答吗,