Python 克隆列表似乎用作别名,即使显式声明为克隆

Python 克隆列表似乎用作别名,即使显式声明为克隆,python,nested-lists,Python,Nested Lists,我在下面的脚本中遇到了一些问题。应制作以下列表的3份副本,以便单独修改。但是,它似乎在创建同一列表的3个克隆,当您修改其中一个克隆时,您将修改所有克隆。以下是函数: def calculateProportions(strategies,proportions): import itertools combinations = [] columns = list(itertools.product(strategies,repeat=3)) for i in range(

我在下面的脚本中遇到了一些问题。应制作以下列表的3份副本,以便单独修改。但是,它似乎在创建同一列表的3个克隆,当您修改其中一个克隆时,您将修改所有克隆。以下是函数:

def calculateProportions(strategies,proportions):
   import itertools
   combinations = []
   columns = list(itertools.product(strategies,repeat=3))
   for i in range(0,len(columns)):
      columns[i] = list(columns[i])
   for n in range(0,len(strategies)):
      combinations.append(columns[:])
   combinations[0][0][0] = "THIS SHOULD ONLY BE IN ONE PLACE"
   print combinations 
strategies = [[0,0],[0,50],[50,50]]
calculateProportions(strategies,[])
请注意,当您运行此命令时,您会看到字符串“this SHOULD IN ONE PLACE”3次(位置[0][0][0]、[1][0][0]和[2][0][0],而不是一次。这似乎是因为列表是用别名组合在一起的,而不是克隆的。但是,我明确克隆了它

我花了最后一个小时的时间在这件事上大发雷霆。非常感谢你提出的解决方案

>>> import copy
>>> help(copy)

在第一行中,您可以看到函数
copy
deepcopy
。这些函数对应于浅拷贝和深拷贝。有关详细信息,请参阅获取列表副本,如
list[:]
不会创建列表中包含的元素的副本(即,它是平面副本,而不是深度副本)。以下示例代码说明了这一点:

>>> n1 = [1, 2]
>>> n2 = [3, 4]
>>> l1 = [n1, n2]
>>> l2 = l1[:]
>>> l2[0] = "was n1" # change in l1 only
>>> l1
[[1, 2], [3, 4]]
>>> l2
['was n1', [3, 4]]
>>> l2[1][0] = "was 3 in n2" # affects both l1 and l2
>>> l1
[[1, 2], ['was 3 in n2', 4]]
>>> l2
['was n1', ['was 3 in n2', 4]]
正如ulidtko所建议的,该模块可能对您的情况有所帮助。

当您编写

l=alist[:]

您正在进行浅层复制。也就是说,列表不同,但两个列表指向相同的对象。因此,如果您修改列表中的一个元素,则另一个列表中的元素也将被修改

你需要进行深度复制,即复制列表和列表中的所有对象

import copy
copy.deepcopy()
仅当您克隆
列时,您才执行了一项操作,即列表已克隆,但其项未克隆,因此在
组合
中使用相同的项引用

您可以使用该函数执行对象的深度复制:

def calculateProportions(strategies,proportions):
    import copy
    import itertools
    combinations = []
    columns = list(itertools.product(strategies, repeat=3))
    for i in range(0, len(columns)):
        columns[i] = list(columns[i])
    for n in range(0, len(strategies)):
        combinations.append(copy.deepcopy(columns))
或者,更简单地说,是:


与其尝试修复深度副本,我只需创建嵌套列表理解的所需数据。这也避免了最终数据的丑陋手动“累积”

def calculateProportions(strategies, proportions):
  import itertools
  combinations = [
    [list(x) for x in itertools.product(strategies, repeat = 3)]
    for strategy in strategies
  ]
  combinations[0][0][0] = "THIS SHOULD ONLY BE IN ONE PLACE"
  print combinations 
def calculateProportions(strategies, proportions):
  import itertools
  combinations = [
    [list(x) for x in itertools.product(strategies, repeat = 3)]
    for strategy in strategies
  ]
  combinations[0][0][0] = "THIS SHOULD ONLY BE IN ONE PLACE"
  print combinations