2010-12-08 27 views
1

J'ai quelques problèmes avec le script suivant. Il devrait faire 3 copies de la liste suivante afin qu'elles puissent être modifiées indépendamment. Cependant, il semble créer 3 clones de la même liste, et quand vous en modifiez un, vous les modifiez tous. Voici la fonction:La liste clonée semble fonctionner comme un alias, même si explicitement déclaré comme un clone

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

Remarquez comment, lorsque vous exécutez cela, vous voyez la chaîne "CELA DEVRAIT ÊTRE DANS UN ENDROIT" 3 fois (position [0] [0] [0], [1] [ 0] [0], et [2] [0] [0], pas une seule fois Cela semble être dû au fait que les listes sont aliasées ensemble plutôt que clonées, mais je les ai clonées explicitement

J'ai passé la dernière heure cognant ma tête dans la table à ce sujet. Vos propositions de solutions sont très appréciées!

Répondre

3

Vous n'effectuez une shallow copy lorsque vous cloner columns, à savoir la liste est cloné, mais ses éléments ne sont pas, de sorte que les mêmes références d'articles sont utilisés dans les combinations et columns.

Vous pouvez utiliser la fonction copy.deepcopy() pour effectuer une copie en profondeur de l'objet:

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

Ou, plus simplement, un 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]) 
0
>>> import copy 
>>> help(copy) 

Dans les premières lignes, vous pouvez voir les fonctions copy et deepcopy. Ceux-ci correspondent à une copie superficielle et profonde. Pour plus de détails, reportez-vous à http://en.wikipedia.org/wiki/Object_copy

0

Obtenir une copie d'une liste comme list[:] ne fait pas créer des copies des éléments contenus dans la liste (à savoir qu'il est une copie plat, pas une copie profonde). Le code exemple suivant illustre ceci:

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

Comme suggéré par ulidtko, le module copy pourrait aider dans votre cas.

0

lorsque vous écrivez

l = alist [:]

vous faites une copie superficielle. c'est-à-dire que la liste est différente, mais les deux listes pointent vers les mêmes objets. donc si vous modifiez un élément d'une liste, l'élément de l'autre liste sera également modifié.

vous devez faire une copie profonde, à savoir. copier la liste et tout l'objet dans la liste.

import copy 
copy.deepcopy() 
0

Au lieu d'essayer de corriger les copies profondes , Je voudrais simplement créer les données souhaitées avec des listes imbriquées. Cela évite également la «accumulation» manuelle laide des données finales.

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