list.append : Merkwürdiger Fehler (Vielleicht Python-Bug)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
drummer123
User
Beiträge: 7
Registriert: Dienstag 10. August 2021, 19:21

Hallo, Ich habe ein Programm geschrieben und finde keine logische Erklärung für den vorhandenen Fehler:

Skript 1:
#define variables
sol_y= [[9,6,1,4],[3,1,2,3]]
new=[]
#new=[[3,1,2,3]]
print("sol_y:"+str(sol_y))
print("---------------")

new.append(sol_y[1]) ######## first step

print("sol_y:"+str(sol_y))
print("new:"+str(new)+"\n")

new[-1].append((8)) ######## second step

print("sol_y:"+str(sol_y))
print("new:"+str(new))

Die Liste sol_y wird nicht verändert, allerdings wird nach "second step" der Wert 8 sowohl an die Liste "new" hinzugefügt (gewollt) als auch an die Liste
"sol_y" (nicht gewollt). Am besten Sie führen das Skript auf Ihrem eigenen PC aus.
Beim Skript 1 mit folgenden Änderungen, tritt der Fehler nicht auf:

Skript 2:
#define variables
sol_y= [[9,6,1,4],[3,1,2,3]]
#new=[]
new=[[3,1,2,3]]
print("sol_y:"+str(sol_y))
print("---------------")

#new.append(sol_y[1]) ######## first step

print("sol_y:"+str(sol_y))
print("new:"+str(new)+"\n")

new[-1].append((8)) ######## second step

print("sol_y:"+str(sol_y))
print("new:"+str(new))

Ich kann mir den Fehler leider nicht erklären. Können Sie mir behilflich sein?

Hier sind noch die Output beider Varianten:
Skript 1:

sol_y:[[9, 6, 1, 4], [3, 1, 2, 3]]
---------------
sol_y:[[9, 6, 1, 4], [3, 1, 2, 3]]
new:[[3, 1, 2, 3]]

sol_y:[[9, 6, 1, 4], [3, 1, 2, 3, 8]]
new:[[3, 1, 2, 3, 8]]


Skript 2:

sol_y:[[9, 6, 1, 4], [3, 1, 2, 3]]
---------------
sol_y:[[9, 6, 1, 4], [3, 1, 2, 3]]
new:[[3, 1, 2, 3]]

sol_y:[[9, 6, 1, 4], [3, 1, 2, 3]]
new:[[3, 1, 2, 3, 8]]
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, das ist kein Python-Fehler. Sondern das übliche Missverständnis, das Listen oder generell alle Objekte durch = kopiert würden. Das ist in Python so nicht. a = irgendwas und b = a bedeuten, dass sowohl a als auch b auf dasselbe(!) irgendwas zeigen. Verändert man das (was bei Listen geht), dann erreicht man über beide Namen a und b das alte, nun veränderte Objekt.

Abhilfe schafft eine explizite Kopie der Liste. Zb mit der Funktion copy.deepcopy. Allerdings ist es meistens eher so, dass man implizit durch zb eine eine List-Komprehension eine neue, veränderte Liste erstellt.
narpfel
User
Beiträge: 690
Registriert: Freitag 20. Oktober 2017, 16:10

@drummer123: pythontutor.com kann das Verhalten sehr schön visualisieren.

Und bitte setze deinen Code in Zukunft in Codeblöcke, damit man ihn lesen kann.
drummer123
User
Beiträge: 7
Registriert: Dienstag 10. August 2021, 19:21

narpfel hat geschrieben: Dienstag 10. August 2021, 21:39 @drummer123: pythontutor.com kann das Verhalten sehr schön visualisieren.

Und bitte setze deinen Code in Zukunft in Codeblöcke, damit man ihn lesen kann.
Vielen Dank für die Antwort. Pythontutor hat mir sehr geholfen. Ich finde zwar diese Verknüpfungen der Listen merkwürdig, aber so ist das eben...
Ich werde versuchen die Codeblöcke zu verwenden.
drummer123
User
Beiträge: 7
Registriert: Dienstag 10. August 2021, 19:21

__deets__ hat geschrieben: Dienstag 10. August 2021, 19:52 Nein, das ist kein Python-Fehler. Sondern das übliche Missverständnis, das Listen oder generell alle Objekte durch = kopiert würden. Das ist in Python so nicht. a = irgendwas und b = a bedeuten, dass sowohl a als auch b auf dasselbe(!) irgendwas zeigen. Verändert man das (was bei Listen geht), dann erreicht man über beide Namen a und b das alte, nun veränderte Objekt.

Abhilfe schafft eine explizite Kopie der Liste. Zb mit der Funktion copy.deepcopy. Allerdings ist es meistens eher so, dass man implizit durch zb eine eine List-Komprehension eine neue, veränderte Liste erstellt.
Danke für die Antwort. Interessantes Verhalten :) .
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist bei den meisten Sprachen so. Java, C#, JS zb. Und bei denen, bei denen es anders ist (hauptsächlich C++) gibt es einen ganzen Zoo anderer Probleme. Resourcen management ist schwer.

Und eine kleine Anmerkung: bitte nicht den Beitrag davor im Vollzitat einfügen. Der steht da ja schon.
narpfel
User
Beiträge: 690
Registriert: Freitag 20. Oktober 2017, 16:10

@drummer123: Das ist in Python nicht nur bei Listen so, sondern bei allen Objekten. `=` verhält sich nicht bei Listen auf magische Weise anders als bei `int`, `str` oder `dict`. Die „korrekte“ Darstellung ist eigentlich diese. Beachte, dass der Pfeil nach `new.append(sol_y[0][0])` auf die selbe `9` zeigt wie der Pfeil in `sol_y[0]`.
Benutzeravatar
snafu
User
Beiträge: 6850
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

drummer123 hat geschrieben: Dienstag 10. August 2021, 22:04 Ich finde zwar diese Verknüpfungen der Listen merkwürdig, aber so ist das eben...
Das hat generell etwas mit dem Konzept von Referenzierung zu tun. Objekte werden halt viel öfter wiederverwendet als es manchem Anfänger bewusst ist. Bei veränderbaren Objekten wie Listen fällt es dann eher auf als z.B. bei Zahlen.
drummer123
User
Beiträge: 7
Registriert: Dienstag 10. August 2021, 19:21

@_deets_ Gibt es eine Funktion, mit der man antworten kann, sodass man sieht, dass ich Ihnen antworte, aber dennoch nicht das Vollzitat eingeblendet
wird? Ich bin neu auf dem Forum und kenne noch nicht die ganzen Funktionen.
drummer123
User
Beiträge: 7
Registriert: Dienstag 10. August 2021, 19:21

Danke an alle Antworten.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst den quote bearbeiten, und zb nur einen Satz zitieren. Aber auch ein einfaches “@user” reicht. Das ist zwar dann nicht mit einer Benachrichtigung verknüpft, aber macht deine Antwort klar, und das ist das wichtige.
Antworten