简体   繁体   English

克隆列表似乎起着别名的作用,即使已明确声明为一个克隆

[英]Cloned list seems to be functioning as an alias, even though explicitly declared as a a clone

I am having some trouble with the following script. 我在使用以下脚本时遇到了一些麻烦。 It should make 3 copies of the following list so that they can be modified independently. 它应制作以下列表的3份副本,以便可以独立修改它们。 However, it seems to be creating 3 clones of the same list, and when you modify one you modify them all. 但是,它似乎正在创建同一列表的3个克隆,并且在修改一个时,您将全部修改。 Here is the function: 这是函数:

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

Notice how, when you run this, you see the string "THIS SHOULD BE IN ONE PLACE" 3 times (position [0][0][0],[1][0][0], and [2][0][0], not once. This appears to be because the lists are aliased together rather than cloned. However I explicitly cloned it. 请注意,在运行此命令时,如何看到字符串“应该在一个位置” 3次(位置[0] [0] [0],[1] [0] [0]和[2] [0 ] [0],不是一次,这似乎是因为列表是一起别名而不是克隆,但是我明确地克隆了它。

I have spent the last hour banging my head into the table on this. 我已经花了最后一个小时将头撞到桌子上。 Your suggested solutions are much appreciated! 非常感谢您提出的解决方案!

You're only performing a shallow copy when you clone columns , ie the list is cloned but its items are not, so the same item references are used in both combinations and columns . 克隆columns时,您仅执行浅表复制 ,即克隆了列表,但没有克隆其项目,因此在combinationscolumns都使用相同的项目引用。

You can use the copy.deepcopy() function to perform a deep copy of the object: 您可以使用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))

Or, more simply, a list comprehension : 或者,更简单地说,是列表理解

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])
>>> import copy
>>> help(copy)

In the very first lines, you can see functions copy and deepcopy . 在第一行中,您可以看到函数copydeepcopy These correspond to shallow and deep copying. 这些对应于浅层复制和深层复制。 For details, refer to http://en.wikipedia.org/wiki/Object_copy 有关详细信息,请参阅http://en.wikipedia.org/wiki/Object_copy

Getting a copy of a list like list[:] does not create copies of the elements contained in the list (ie it is a flat copy, not a deep copy). 获取类似list[:]的列表的副本不会创建列表中包含的元素的副本(即,它是平面副本,而不是深层副本)。 The following example code illustrates this: 以下示例代码对此进行了说明:

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

As suggested by ulidtko, the copy module might help in your case. 如ulidtko所建议, 复制模块可能对您有帮助。

when you write 当你写

l = alist[:] l = alist [:]

you're doing a shallow copy. 您正在执行浅表复制。 that is to say that the list is different, but the two lists are pointing to the same objects. 也就是说,列表不同,但是两个列表指向相同的对象。 so if you modify one element of a list, the element in the other list will be modified too. 因此,如果您修改列表中的一个元素,则另一个列表中的元素也会被修改。

you need to make a deep copy, ie. 您需要进行深拷贝,即。 copying the list and all the object in the list. 复制列表和列表中的所有对象。

import copy
copy.deepcopy()

Instead of trying to fix up the deep copies, I would just create the desired data with nested list comprehensions. 我不会尝试修复深层副本,而只是使用嵌套列表推导来创建所需的数据。 This also avoids the ugly manual "accumulation" of the final data. 这也避免了最终数据的繁琐的手动“累积”。

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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM