2010-12-08 10 views
1

Ich habe einige Probleme mit dem folgenden Skript. Es sollte 3 Kopien der folgenden Liste erstellen, damit sie unabhängig voneinander geändert werden können. Es scheint jedoch, 3 Klone der gleichen Liste zu erstellen, und wenn Sie eine ändern, ändern Sie sie alle. Hier ist die Funktion:Cloned Liste scheint als ein Alias ​​zu funktionieren, obwohl explizit als ein Klon erklärt

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

Beachten Sie, wie, wenn Sie dies ausführen, sehen Sie die Zeichenfolge "DIES IN EINEM ORT sollte" 3-mal (Position [0] [0] [0], [1] [ 0] [0], und [2] [0] [0], nicht einmal.Das scheint zu sein, weil die Listen zusammen aliased anstatt geklont sind. Jedoch habe ich es explizit geklont.

Ich habe die letzte Stunde verbracht mein Kopf in die Tabelle auf diese hämmern. Ihre Lösungsvorschläge sind sehr willkommen!

Antwort

3

Sie ausführen, nur ein shallow copy wenn Sie columns klonen, das heißt die Liste geklont wird aber seine Elemente sind nicht, so dass die gleichen Positionsnummern verwendet werden, sowohl in combinations und columns.

können Sie verwenden, um die copy.deepcopy() Funktion eine tiefe Kopie des Objekts auszuführen:

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

Oder, einfacher gesagt, ein 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

bekommt eine Kopie einer Liste wie list[:] tut nicht Kopien der in der Liste enthaltenen Elemente erstellen (das heißt, es ist eine flachen Kopie, keine tief Kopie). Der folgende Beispielcode veranschaulicht dies:

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

Wie ulidtko vorgeschlagen, das copy Modul in Ihrem Fall helfen könnte.

0

wenn Sie

l = alist schreiben [:]

Sie tun eine flache Kopie. Das heißt, die Liste ist anders, aber die beiden Listen verweisen auf dieselben Objekte. Wenn Sie also ein Element einer Liste ändern, wird auch das Element in der anderen Liste geändert.

Sie müssen eine tiefe Kopie machen, dh. Kopieren der Liste und aller Objekte in der Liste.

import copy 
copy.deepcopy() 
0

Anstatt die tiefen Kopien zu reparieren versuchen, , Würde ich nur die gewünschten Daten mit verschachtelten Listenkompromittierungen erstellen. Dies vermeidet auch die hässliche manuelle "Anhäufung" der endgültigen Daten.

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