2

我在使用以下脚本时遇到了一些问题。它应该制作以下列表的 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,[])

请注意,当您运行此程序时,您会看到字符串“这应该在一个地方”3 次(位置 [0][0][0]、[1][0][0] 和 [2][0] ][0],不是一次。这似乎是因为列表是一起别名而不是克隆的。但是我明确地克隆了它。

我花了最后一个小时把头撞到桌子上。非常感谢您提出的解决方案!

4

5 回答 5

4

您仅在 clone 时执行浅拷贝columns,即克隆列表但未克隆其项目,因此在combinations和中使用相同的项目引用columns

您可以使用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 = []
    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([item[:] for item in columns])
于 2010-12-08T08:58:09.727 回答
0
>>> import copy
>>> help(copy)

在第一行,您可以看到函数copydeepcopy. 这些对应于浅拷贝和深拷贝。有关详细信息,请参阅http://en.wikipedia.org/wiki/Object_copy

于 2010-12-08T08:52:22.300 回答
0

获取列表的副本不会创建列表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 所建议的那样,复制模块可能会对您的情况有所帮助。

于 2010-12-08T08:57:18.733 回答
0

当你写

l = alist[:]

你正在做一个浅拷贝。也就是说列表不同,但是两个列表指向的是同一个对象。因此,如果您修改列表中的一个元素,则另一个列表中的元素也将被修改。

你需要做一个深拷贝,即。复制列表和列表中的所有对象。

import copy
copy.deepcopy()
于 2010-12-08T08:57:57.500 回答
0

我不会尝试修复深层副本,而是使用嵌套列表推导创建所需的数据。这也避免了最终数据的丑陋手动“积累”。

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 
于 2010-12-08T09:17:55.133 回答