Warum ändert der Operator + keine Liste während .append ()?

7

Ich arbeite durch Udacity und Dave Evans führte eine Übung über Listeneigenschaften ein

%Vor%

Die Ausgabe ist

%Vor%

Also in einer Funktion das Hinzufügen einer 6 zum Set nicht angezeigt, aber es tut, wenn nicht in einer Funktion?

    
canyon289 25.05.2012, 03:33
quelle

6 Antworten

15
  

Also in einer Funktion das Hinzufügen einer 6 zum Set nicht angezeigt, aber es tut, wenn nicht in einer Funktion?

Nein, das passiert nicht.

Was passiert, wenn Sie mylist = mylist + [6] ausführen, erstellen Sie effektiv eine komplett neue Liste und fügen sie in die lokale Variable mylist ein. Diese Variable mylist verschwindet nach der Ausführung der Funktion und die neu erstellte Liste wird ebenfalls verschwinden.

OTOH Wenn Sie mylist.append(6) ausführen, erstellen Sie keine neue Liste. Sie erhalten die Liste bereits in der Variablen mylist und fügen dieser Liste ein neues Element hinzu. Das Ergebnis ist, dass die Liste (auf die auch list2 zeigt) selbst geändert wird. Die Variable mylist wird wieder verschwinden, aber in diesem Fall haben Sie die ursprüngliche Liste geändert.

Lassen Sie uns sehen, ob Ihnen eine mehr visuelle Erklärung helfen kann:)

Was passiert, wenn Sie proc() aufrufen?

Wenn Sie list1 = [1, 2, 3, 4, 5] schreiben, erstellen Sie ein neues Listenobjekt (auf der rechten Seite des Gleichheitszeichens) und erstellen eine neue Variable, list1 , die auf dieses Objekt zeigt.

Dann, wenn Sie proc() aufrufen, erstellen Sie eine weitere neue Variable, mylist , und da Sie list1 als Parameter übergeben, zeigt mylist auf das gleiche Objekt:

Die Operation mylist + [6] erzeugt jedoch ein ganz neues Listenobjekt , dessen Inhalt der Inhalt von mylist plus dem Inhalt des folgenden Listenobjekts ist - also [6] . Da Sie dieses neue Objekt mylist zuweisen, ändert sich unser Szenario ein wenig und mylist zeigt nicht mehr auf das gleiche Objekt, auf das list1 zeigt:

Was ich nicht gesagt habe, ist, dass mylist eine lokale Variable ist: Sie verschwindet nach dem Ende der Funktion proc() . Wenn die Ausführung von proc() beendet ist, ist mylist verschwunden:

Da keine andere Variable auf das von mylist + [6] erzeugte Objekt zeigt, wird es ebenfalls verschwinden (da der Garbage Collector * es sammelt):

Beachten Sie, dass das Objekt, auf das von list1 gezeigt wird, am Ende nicht geändert wird.

Was passiert, wenn Sie proc2() aufrufen?

Alles ändert sich, wenn Sie proc2() aufrufen. Am Anfang ist es dasselbe: Sie erstellen eine Liste ...

... und übergeben Sie es als Parameter an eine Funktion, die eine lokale Variable erzeugen wird:

Anstatt jedoch den Operator + concatenation zu verwenden, der eine neue Liste generiert, wenden Sie die Methode append() auf die vorhandene Liste an. Die Methode append() erstellt kein neues Objekt ; Statt dessen ändert es _ das vorhandene:

Nach dem Ende der Funktion wird die lokale Variable verschwinden, aber das ursprüngliche Objekt, auf das sie zeigt, und von list1 wird bereits geändert:

Da auf list1 immer noch hingewiesen wird, wird die ursprüngliche Liste nicht zerstört.

BEARBEITEN : Wenn Sie einen Blick auf all diese Dinge werfen möchten, die vor Ihren Augen geschehen , gehen Sie einfach zu diese radikal erstaunliche Simulator :

* Wenn Sie nicht wissen, was Müllsammler ist ... nun, Sie werden bald nach dem Verständnis Ihrer eigenen Frage entdecken.

    
brandizzi 25.05.2012, 03:40
quelle
3

Variablen in Python können immer als Referenzen betrachtet werden. Wenn Sie eine Funktion mit einem Argument aufrufen, übergeben Sie einen Verweis auf die tatsächlichen Daten.

Wenn Sie den Zuweisungsoperator ( = ) verwenden, weisen Sie diesen Namen einem neuen Objekt zu. Also erstellt mylist = mylist + [6] eine neue Liste, die den alten Inhalt von mylist sowie 6 enthält, und weist die Variable mylist zu, um auf die neue Liste zu verweisen. list1 zeigt immer noch auf die alte Liste, so dass sich nichts ändert.

Wenn Sie andererseits .append verwenden, hängt das tatsächlich ein Element an die Liste an, auf die sich die Variable bezieht - es weist der Variablen nichts Neues zu. Ihre zweite Funktion ändert also die Liste, auf die sich list2 bezieht.

    
happydave 25.05.2012 03:41
quelle
2

Normalerweise könnten Sie im ersten Fall in der Funktion proc die globale Liste nur durch Zuweisung ändern, wenn Sie

deklariert haben %Vor%

zuerst und übergab mylist nicht als Parameter. In diesem Fall erhalten Sie jedoch eine Fehlermeldung, dass mylist global und lokal ist: %Code%. Was in name 'mylist' is local and global passiert, ist, dass eine lokale Liste erstellt wird, wenn die Zuweisung stattfindet. Da lokale Variablen weggehen, wenn die Funktion endet, werden die Auswirkungen von Änderungen an der lokalen Liste nicht auf den Rest des Programms übertragen, wenn sie später ausgedruckt werden.

Aber in der zweiten Funktion proc modifizierst du die Liste, indem du sie anfügst anstatt sie zuzuweisen, also wird das proc2 Schlüsselwort nicht benötigt und die Liste wird an anderer Stelle angezeigt.

    
Levon 25.05.2012 03:37
quelle
0

Dies ist in der einen oder anderen Form eine sehr häufige Frage. Ich habe einen Fehler gemacht, als ich erklärte, dass Python-Parameter mich vor ein paar Tagen . Im Grunde erstellt eine davon eine neue Liste und die andere ändert die bestehende Liste. Im letzteren Fall "sehen" alle Variablen, die auf die Liste verweisen, die Änderung, weil sie immer noch das gleiche Objekt ist.

    
kindall 25.05.2012 04:23
quelle
0

In der dritten Zeile hast du das gemacht

%Vor%

Also, wenn Sie das Folgende nach der obigen Zeile gemacht haben,

%Vor%

welche list1 gedruckt hat, die Sie beim Start und bei der proc-Prozedur erstellt haben, die list1 + [6] hinzufügt, die eine neue Liste innerhalb der Funktion proc erstellt. Wenn Sie [6] anhängen, erstellen Sie keine neue Liste, sondern fügen ein Listenelement an die bereits vorhandene Liste an.

Aber denken Sie daran. In Zeile 7 haben Sie die Liste erneut erstellt

%Vor%

Nun wollten Sie die Liste1 drucken, indem Sie sie explizit aufrufen. Dadurch wird die Liste1 ausgedruckt, die Sie erneut initialisiert haben, aber nicht die vorherige.

    
user907629 25.05.2012 08:00
quelle
0

Neben den bereits gegebenen umfassenden Antworten ist es auch wichtig, dass Sie wissen, dass Sie dieselbe Syntax wie folgt haben möchten:

%Vor%

... aber die Liste soll "vor Ort" aktualisiert werden, können Sie Folgendes tun:

%Vor%

Was, obwohl es so aussieht, als würde es das Gleiche wie die erste Version machen, ist tatsächlich dasselbe wie:

%Vor%

(Beachten Sie, dass extend den Inhalt eines iterablen Objekts annimmt und einzeln addiert, während append das erhält, was ihm gegeben wird und fügt es als einzelnes Element hinzu. Siehe Anfügen und Erweitern für eine vollständige Erklärung.)

    
Owen 07.06.2012 11:35
quelle

Tags und Links