2016-10-09 2 views
5

Ich habe den folgenden Code, warum der erste ändert sich nicht alist, während der zweite ändert es?Python: eine Liste der Liste loopen und Wert innerhalb der Schleife zuweisen

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item = 1 
print(alist) 

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item = item.append(10) 
print(alist) 
+0

Zuerst ändern, wenn es wie folgt verwendet wird: 'für Element in Alist: Alist [Alist.Index (Element)] = 1' So' Element' ist lokale Variable in einer Schleife, nichts außerhalb tun. – dsgdfg

Antwort

5

Dies ist ein etwas unintuitives Verhalten von Variablen. Dies geschieht, weil Variablen in Python immer Verweise auf Werte sind.

Boxen und Tags

In einigen Sprachen, neigen wir dazu, über Variablen als „Box“ zu denken, wo wir Werte setzen; In Python sind sie jedoch Verweise und verhalten sich eher wie Tags oder "Spitznamen" zu Werten. Wenn Sie also 1 bis item zuweisen, ändern Sie nur die Variablenreferenz und nicht die Liste, auf die sie verweist.

Eine grafische Darstellung kann helfen. Das Bild stellt unter die Liste von alist = [[1,2], [3,4], [5,6]] erstellt

A list with three sublists

Da wollen wir sehen, was passiert, wenn wir Ihre erste Schleife auszuführen.

Die erste Schleife

Wenn Sie for item in alist ausführen, fragen Sie die Interpreter jeden Wert aus der Liste zu nehmen, eine pro Zeit, legt es auf der Variable item und in ihm eine Operation zu tun. Bei der ersten Operation, zum Beispiel, haben wir dieses neue Schema:

Now a variable points to a sublist

Beachten Sie, dass wir die Teilliste item nicht kopieren; stattdessen wir Punkt zu ihm durch item. Dann führen wir item = 1 aus - aber was bedeutet das?Es bedeutet, dass wir 1, statt zeigte auf den sublist item Punkt auf den Wert machen:

item points to other value now

Beachten Sie, dass die alte Referenz verloren geht (es ist der rote Pfeil) und jetzt haben wir eine neue. Aber wir haben gerade eine Variable geändert, die auf eine Liste zeigt - wir haben die Liste selbst nicht verändert.

Dann treten wir in die zweite Iteration der Schleife, und jetzt item Punkte auf dem zweiten Teilliste:

item pointing to the second sublist

Wenn wir item = 1 ausführen, wieder, wir haben nur den variablen Punkt aonther Wert machen , ohne die Liste zu ändern:

enter image description here

Nun, was passiert, wenn wir die zweite Schleife ausführen?

Die zweite Schleife

Die zweite Schleife beginnt wie die erste stellen wir nach item zur ersten Subliste beziehen:

Now a variable points to a sublist

Der erste Unterschied ist jedoch, dass wir item.append() nennen. append() ist eine Methode, so dass es den Wert des Objekts ändern kann, das es aufruft. Wie wir verwenden, senden wir eine Nachricht an das Objekt von item, um den Wert 10 anzuhängen. In diesem Fall ist die Operation nicht in der Variablen gemacht, aber direkt in dem Objekt es bezieht sich! So, hier ist das Ergebnis des Aufrufs item.append():

A list has grown

Allerdings haben wir nicht nur Wert auf die Liste anhängen! Wir weisen auch den von item.append() zurückgegebenen Wert zu. Dies wird den item Verweis auf die Unterliste trennen, aber hier ist ein Haken: append() gibt None zurück.

enter image description here

Der None Wert

None ist ein Wert, der im Grunde genommen die Nichtverfügbarkeit eines entsprechenden Wert darstellt. Wenn eine Funktion None zurückgibt, heißt es meistens: "Ich habe nichts Relevantes, um Sie zurückzugeben." append() ändert seine Liste direkt, so dass es nichts gibt, das zurückgegeben werden muss.

Es ist wichtig, weil Sie wahrscheinlich geglaubt haben item würde auf die angefügte Liste [1, 2, 10], Recht verweisen? Nein, jetzt zeigt es auf None. Also, Sie würden den Code unten erwarten ...

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item = item.append(10) 
    print(item) 

Um so etwas wie dieses Motiv:

[1, 2, 10] 
[3, 4, 10] 
[5, 6, 10] 

Aber diese ist nicht passieren. Diese ist, was passiert:

>>> alist = [[1,2], [3,4], [5,6]] 
>>> for item in alist: 
...  item = item.append(10) 
...  print(item) 
... 
None 
None 
None 

Doch wie wir kommentierte die append() Methode die Listen selbst verändert. Also, während die Variable nach der Zuweisung nutzlos war, wird die endgültige Liste geändert!

>>> print alist 
[[1, 2, 10], [3, 4, 10], [5, 6, 10]] 

Wenn Sie die beigefügten Liste innerhalb der Schleife verwenden möchten, ordne einfach nicht die Methode zurückgegebenen Wert zu item. Tun Sie dies:

>>> alist = [[1,2], [3,4], [5,6]] 
>>> for item in alist: 
...  item.append(10) 
...  print item 
... 
[1, 2, 10] 
[3, 4, 10] 
[5, 6, 10] 

Dies funktioniert, weil item noch auf der Liste verweisen.

Fazit

Referenzen sind etwas komplex zunächst, geschweige denn Meister zu verstehen. Sie sind jedoch sehr mächtig und können gelernt werden, wenn Sie Beispielen folgen. Ihr Beispiel ist ein bisschen kompliziert, weil hier mehr passiert.

Die Python Tutor kann Ihnen helfen zu verstehen, was vor sich geht, weil es jeden Schritt grafisch ausführt. Check your own code running there!

1

Referenzierung the document:

Die for-Schleife macht Zuordnungen zu den Variablen (n) in der Zielliste. Dies überschreibt alle bisherigen Aufgaben zu diesen Variablen einschließlich gemacht die in der Suite der for-Schleife:

for i in range(10): 
    print(i) 
    i = 5    # this will not affect the for-loop 
         # because i will be overwritten with the next 
         # index in the range 

So Ihr zweites Beispiel ist identisch mit:

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item.append(10) # this statement modifies each item in alist 
         # , which is what item the variable "points to" 
print(alist) 

Das heißt item ist eine neue Variable in jeder Iteration. Daher ist das Zuweisen von Werten in einer bestimmten Iteration sinnlos, da der Wert zu Beginn der nächsten Iteration durch den Verweis auf das nächste Element in alist außer Kraft gesetzt wird.

2

Sie vergessen, dass list.append() die Liste nicht selbst zurückgibt, aber die Liste tatsächlich ändert?

item = 1 funktioniert wie erwartet. Für den Rest der for-Schleife ist das Element jetzt 1 und nicht die Liste, die es ursprünglich war. Es wird nicht neu zugewiesen, was item ist, das ist nicht was For-Schleifen tun.

jedoch in der zweiten Schleife, sind Sie jetzt item = None zuweisen, da die Append Funktion nichts zurückliefert, aber es fügt das Element der Liste an Ort und Stelle:

>>> L = [1, 2, 3] 
>>> L.append(4) 
>>> L 
[1, 2, 3, 4] 

So ist Ihr Code im Grunde Sprich "Gehe durch jede Unterliste in meiner Hauptliste und füge 10 hinzu".

0

Wenn Sie schreiben

for item in alist: 

Sie sind in liast in der item Variable eine Kopie jedes Element tatsächlich zu schaffen, und Sie sind nicht einen Verweis auf item bekommen.

append ändert jedoch die Liste in-Ort und gibt keinen Wert zurück, und deshalb erhalten Sie die Werte in None geändert (aufgrund der Zuordnung - wenn Sie es entfernen, erhalten Sie die anhängende Arbeit fein).

+0

'für jeden' ​​Block in Python macht keine Kopie, d. H.' Item' zeigt auf jedes Mitglied von 'alist' in jeder Iteration. – SuB

2

Der Operator = ändert im zweiten Code keine Änderungen. .append verursacht Änderungen in alist. Verwenden Sie die folgende Zeile als dritte Zeile im zweiten Code. Sie werden das gleiche Ergebnis sehen:

item.append(10) 

Im ersten Code item Punkt zu einem anderen Objekt durch item=1, so alist nicht ändern. Im zweiten Code machen Sie die Änderung alist durch Aufruf append Methode davon.

4

Im ersten Beispiel item wird auf jedes Element in der Liste alist, gebunden ist und dann itemRebound die ganzzahligen 1. Dies ändert nicht das Element der Liste - es nur bindet den Namen item zu dem int Objekt 1. Im zweiten Beispiel wird das Listenelement (selbst eine Liste) durch append() mutiert. item ist immer noch an die Unterliste gebunden, so item.append() mutiert die Unterliste.

2

Es ist Zeigervariable in Python.

Das erste Beispiel:

for item in alist: 
    item = 1 

jedes Element zu jedem _ITEM in alist zeigt aber plötzlich Sie das Element Wert zu ändern, die nicht von dem Wert des _ITEM in alist als Ergebnis nichts ändern zu alist

Das zweite Beispiel:

for item in alist: 
    item = item.append(10) 

jedes Element zu jedem _ITEM in alist zeigt, und dann etwas mit dem Element, das Sie den gleichen Speicherplatz teilen anhängen _item, als Ergebnis wird der Wert von _item in Alist geändert und Alist wird ebenfalls geändert.

Verwandte Themen