Problem mit Liste

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
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Hallo,

Ich habe hier zwei Beispiele:

Code: Alles auswählen

item=[0]
liste=[]
for i in range(5):
    item[0]+=1
    liste+=item
print liste

item=[0]
liste=[]
for i in range(5):
    item[0]+=1
    liste+=[item]
print liste
Bei beiden Beispielen sollen aufsteigend Werte in eine Liste einfügt werden. Beim zweiten Beispiel sollte eine Liste mit Listen der jeweiligen Werte entstehen. Das geschieht auch, aber jeder Wert ist gleich dem letzten.
Warum?
Der einzige Unterschied zwischen dem ersten und dem zweiten Beispiel ist:

Code: Alles auswählen

[item]
Zuletzt geändert von HarryH am Dienstag 20. Januar 2004, 16:02, insgesamt 1-mal geändert.
Gruß, Harry
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
HarryH hat geschrieben:Warum?
Kommt noch besser:

Code: Alles auswählen

item=[0]
liste=[]
for i in range(5):
    item[0]+=1
    liste+=[item]
print liste
liste[2][0] = 4711
print liste
Ausabe:
[[5], [5], [5], [5], [5]]
[[4711], [4711], [4711], [4711], [4711]]

Grund: Du hast die eine Liste item fünfmal in die Liste liste gepackt, oder anders gesagt: Die Liste liste enthält fünf Referenzen auf ein einziges Objekt, nämlich die Liste item.
Abhilfe: liste+=[item[:]]

Jan
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi HarryH,

schau dir mal den Thread zu __init__ an, weiter unten gehts um OOP, Objekte und Instanzen.

liste+=item bedeutet: erweitere Liste um alle Einträge von der Liste auf die item zeigt. Daher wird immer der aktuelle Eintrag genommen.
liste+=[item] bedeutet: erweitere Liste um eine neue Liste mit dem Eintrag des Objekts (in dem Fall die liste mit dem einen Element), auf das item zeigt. Dies zeigt immer auf die Liste mit dem einen Element, Du kannst das leicht überprüfen indem Du an Dein Programm

Code: Alles auswählen

item[0] += 1
print liste
anfügst. Es wird eben keine Kopie der Liste auf die item zeigt angefügt, sondern der Verweis auf die Liste auf die item zeigt.
liste+=[item[:]] löst Dein Problem, da jetzt, durch das slizing [:] eine neue Liste erstellt wird und der Verweis auf die neue Liste zu liste hinzugefügt wird.


Gruß

Dookie
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

@Voges: Da war ich wohl zu langsam bei Tippen ;)
Aber immerhin sind wir uns einig 8)


Gruß

Dookie
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Danke für eure wirklich schnellen Antworten.
Das mit dem Klone war mir bekannt und ich habe es bereits auch schon so gehandhabt. Nur wußte ich nicht, weshalb es nötig war. Deshalb meine Fragen.
So wie ich das nun verstanden habe ist [item] die Referenz auf item[...]. Sobald ich nun item[...] ändere, ändert sich ebenfalls [item] und das egal wo es sich befindet und wie oft es existiert. Ist das richtig so?
Gruß, Harry
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Nicht ganz.
item ist eine referenz auf eine liste [...]. Die liste selber hat keinen Namen, nur eine Adresse im Speicher. Wie im anderen Thread von mir beschrieben, stell dir Variablen wie item vor als Zettelchen auf denen ein Verweis (Adresse) von einem Objekte (Instanz) eingetragen. Daher bekommst Du wenn sich das Objekt ändert in jeder Variablen die auf dieses Objekt zeigt die Veränderung mit.


Gruß

Dookie
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

...gelöscht...

[Wieso kann ich den Beitrag nicht löschen? Manchmal geht das.]
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Dookie hat geschrieben:diesmal war ich schneller *ggg*
auch nicht ganz richtig
Das war völliger Keks. Deswegen hab' ich das schnell - aber nicht schnell genug ;-) - wieder gelöscht.
Jan
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Also:
Listen sind Kisten.
Kiste "item" ist noch leer.
Dann tue ich einen Apfel hinein.
Als nächstes packe ich diese Kiste "item" mit dem Apfel in eine "große" Kiste (namens "liste"), aber nicht direkt sondern nur als Referenz.
Beim nächsten Durchlauf tue ich in Kiste "item" einen weiteren Apfel. Nun ändert sich die erste Referenz in der großen Kiste auf zwei Äpfel. Dann packe ich erneut die Kiste "item" in die "große" Kiste, wiederum nur als Referenz. Somit habe ich nun in der großen Kiste zwei gleiche Referenzen auf die Kiste "item" .
.... usw.
Zum Schluß frage ich:
Wie viele Kisten sind in der großen Kiste? -> 5 Kisten, namens item.
Und wieviele Äpfel sind in Kiste "item"? -> 5 Äpfel

Ist mein Beispiel richtig?

Nachtrag: Wenn ich Referenz schreibe, meine ich die anonyme Kiste mit der ich Kiste "item" in die große Kiste packe. Da sie keinen Namen hat, kann sie also nur ein Bezug zu Kiste "item" sein, mehr nicht.
Gruß, Harry
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Noch immer nicht ganz.

es gibt keine Kiste item, nur ein Zettelchen item, auf dem die GPS-Koordinate einer beliebigen Kiste stehen kann. Du verlangs vom Kistenbauer (Listklasse) er soll eine neue Kiste machen, und Du schreibst auf das Zettelchen "item" die GPS-Koordinate der neuen Kiste, die dir der Kistenbauer zurückgeliefert hat. Er hat dir nur die Koordinate der Kiste zurückgeliefert, die Kiste steht irgendow auf de Speicher und bleibt auch immer dort. Jetzt gehst Du mit dem Zettelchen "item" und einem GPS-Empfänger auf den Speicher und gehst zu der Koordinate, die auf dem Zettelchen "item" steht. dort findest Du eine Kiste in die du jetzt fünf Zettelchen legst, auf dem die GPS-Koordinaten von einem Apfel notiert ist. Jetzt siehst Du dir einen Zettel aus der Kiste an und schreibst die Koordinaten von dem Apfel auf einen Zettel "meinApfel". Mit dem Zettel "mein Apfel" gehst Du jetzt zu den Koordinaten die darauf notiert sind und findest einen Apfel. jetzt beisst Du von dem Apfel ab.
F: Was ist in der Kiste?
A: Immer noch fünf Zettelchen mit den Koordinaten von ein und dem selben Apfel, von dem Du ein Stück abgebissen hast.

Objekte sind immer Anonym, haben also keinen Namen, ganz egal ob Liste Dictionary, oder sonstwas, genaugenommen sind auch Integer und Floats anonym allerdings sind diese imutable, also nicht veränderbar. wenn Du was ausrechnest, wird ein neues Objekt mit dem Ergebnis erzeugt und die Referenz des Ergebnisses einer Variablen zugewiesen. Die einzige Ausnahme sind Funktionen, wobei selbs diese anonymisiert werden können.


Gruß

Dookie
Zuletzt geändert von Dookie am Dienstag 20. Januar 2004, 17:08, insgesamt 1-mal geändert.
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

HarryH hat geschrieben:Als nächstes packe ich diese Kiste "item" mit dem Apfel in eine "große" Kiste (namens "liste"), aber nicht direkt sondern nur als Referenz.
Beim nächsten Durchlauf tue ich in Kiste "item" einen weiteren Apfel. Nun ändert sich die erste Referenz in der großen Kiste auf zwei Äpfel. Dann packe ich erneut die Kiste "item" in die "große" Kiste, wiederum nur als Referenz. Somit habe ich nun in der großen Kiste zwei gleiche Referenzen auf die Kiste "item" .
.... usw.
Zum Schluß frage ich:
Wie viele Kisten sind in der großen Kiste? -> 5 Kisten, namens item.
Und wieviele Äpfel sind in Kiste "item"? -> 5 Äpfel
Meine Variante:
Als nächstes lege ich in die "große" Kiste (namens "liste") einen Zettel, wo die Kiste "Item" zu finden ist (2433. Regalbrett, 3123. Kistenplatz von links, das wäre die Postion im Speicher). Beim nächsten Durchlauf tue ich in Kiste "item" einen weiteren Apfel und lege (warum auch immer) einen weiteren Zettel mit der Kistenposition in die Kiste "liste".
.... usw.
Zum Schluß frage ich:
Wie viele Kisten sind in der großen Kiste? -> keine, aber 5 Zettel mit demselben Inhalt, nämlich der Information, wo die Kiste "Item" zu finden ist.
Und wieviele Äpfel sind in Kiste "item"? -> 5 Äpfel

So, und jetzt muss ich mir Dookies noch durchlesen ;-)
Jan
Antworten