2013-06-13 2 views
5

Lassen Sie uns sagen, dass ich eine 2D-Python-Liste mit allen 0en initialisiert werden soll, ich etwas tun würde:Initialisierung von 2D-Listen in Python: Wie werden tiefe Kopien jeder Zeile erstellt?

test = [[0.0] * 10] * 10 

Dann beginne ich Werte in der ersten Liste zu modifizieren ...

test[0][0] = 1.0 

Aber das betrifft das erste Element aller Listen aus irgendeinem Grund:

print test 

[[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] 

Was ist damit los? Warum macht es eine tiefe Kopie der inneren Liste, aber eine flache Kopie der äußeren Liste?

Antwort

4

tun [[0.0] * 10] * 10 schafft tatsächlich mehrere Kopien derselben Liste so eine Modifizierung werden alle von ihnen beeinflussen:

>>> test = [[0.0] * 10] * 10 
>>> [id(x) for x in test]  #see all IDs are same 
[3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L] 

Versuchen Sie folgendes:

>>> test = [[0.0]*10 for _ in xrange(10)] 
>>> test[0][0] = 1.0 
>>> test 
[[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] 

Integers/Schwimmer sind unveränderlich, während Listen wandelbar sind :

>>> x = y = [] 
>>> x is y  # Both point to the same object 
True 
>>> x.append(1) # list.extend modifies a list in-place 
>>> x,y   # both references to [] can see the modification 
([1], [1]) 
>>> x = y = 1 
>>> x is y  #both points to the same object 
True 
>>> x+=1  # only x gets modified, it now points to a new object 2 
>>> x,y   # y still points to the same object 1 
(2, 1) 
+0

Wie seltsam! Ich verstehe nicht * warum * es würde tiefe Kopien der inneren Liste machen ('[0.0] * 10'), aber flache Kopien der äußeren Liste (' ([0.0] * 10) * 10') –

+1

' 0.0] * 10 'erzeugt '[0.0, 0.0, ...]'. Ganzzahlen und Gleitkommazahlen sind in Python unveränderlich, obwohl alle Elemente dieser Liste auf das gleiche Objekt 0.0 verweisen, aber das Ändern von eins wirkt sich nicht auf andere Objekte aus, da sie unveränderlich sind. Auf der anderen Seite sind Listen veränderbar, das Ändern einer Kopie wirkt sich auch auf alle anderen Referenzen aus. –

3

Die Liste test enthalten s mehrere Iterationen der gleichen Liste, daher eine Änderung in einem (wie Sie durch die Neuzuweisung des ersten Elements von test[0] machen) wird in allen anderen widerspiegelt. Versuchen Sie stattdessen:

[[0.0]*10 for _ in xrange(10)] # or `range` in Python 3.x 

Natürlich würden Sie nicht darüber müssen sich Sorgen zu machen, wenn alles, was Sie [0.0] * 10 war hatte, da dies eine Liste von Ints schafft, von denen keiner jemals mutieren kann. Auf der anderen Seite sind Listen tatsächlich änderbar.

+1

+1 für auch die alternative Python 3 Syntax geben. –

Verwandte Themen