Anfängerfrage zu Listen

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
kruhling
User
Beiträge: 4
Registriert: Sonntag 31. Dezember 2017, 18:50

Hallo zusammen,

ich habe gerade angefangen, mich mit Python zu beschäftigen und bin dabei auf Problem gestoßen.
Ich kenne es von anderen Sprachen, dass die Anweisung

liste2=liste3

die liste3 in die liste2 kopiert. Danach ist liste3 noch vorhanden, nur eben kopiert und somit doppelt.
Beim Üben bin ich nun darauf gestoßen, dass Python das offenbar anders macht. Ich habe ein kleines Beispielprogramm geschrieben ( eine Übung aus einem Buch ):

# 2. Programm zu Listen
# Liste initialisieren
namen=[]

# MAIN
print "Gib bitte 5 Namen ein:"

for i in range(5):
tempname=raw_input()
namen.append(tempname)

# ursprüngliche Liste in sortname ablegen und dann sortnamen sortieren
sortnamen=namen
sortnamen.sort()
print namen
print sortnamen

Wenn ich das so tue und dann namen und sortnamen ausgebe, sind sie gleich. Mache ich hier etwas falsch, oder was löst dieses Verhalten aus?
Vielen Dank für eure Hilfe.
Gruß, Kruhling
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Bitte setze deinen Code das nächste mal in Python-Code-Tags, damit das hier entsprechend formatiert wird. Sonst ist der Code kaum lesbar.
In Python wird das IMO so gehandhabt, wie in jeder anderen Sprache die ich kenne (Java, C, C# usw. usf) auch: der Inhalt des rechts vom "="-Zeichen stehenden Bezeichners wird in den links vom "="-Zeichen stehenden Bezeichners übergeben. Beide Variablen, bzw. deine Liste namen und sortnamen *zeigen* dabei auf die selbe Speicheradresse in deinem RAM.
When we say computer, we mean the electronic computer.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Code: Alles auswählen

liste2 = liste1
Versuche es so zu sehen;
Der Variablenname liste1 ist eine Referenz, ein Pointer/Zeiger auf eine Liste von Objekten.
Bei der Zuweisung wird diese Referenz kopiert, aber nicht eine Kopie der Liste erzeugt.

Wenn du eine Kopie erzeugen willst, gibt es dafür mehrere Möglichkeiten:

Code: Alles auswählen

# slicing
liste2 = liste1[:]

# Benutzung der list() Funktion
liste2 = list(liste1)

# Benutzung des copy Moduls, ist aber langsamer
import copy
liste2 = copy.deepcopy(liste1)
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@kruhling: Für das, was Du möchtest, gibt es die Funktion 'sorted'. Dann solltest Du berücksichtigen, dass 'Variablen' in Python tatsächlich stets Referenzen auf Objekte sind. So legt 'a = b' beispielsweise mit a eine zweite Referenz auf das Objekt an, welches bereits durch b referenziert wird. Wichtig für das weitere Verständnis ist die Unterscheidung von mutablen und immutablen Datentypen.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Wenn du die englische Sprache einigermaßen verstehst, schau dir mal diesen Talk an,
insbesondere die ersten 20 min behandeln diese Thematik.
Learn Python by Immersion https://www.youtube.com/watch?v=hPECpDHHjoI
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

sls hat geschrieben: Sonntag 1. Juli 2018, 10:13 In Python wird das IMO so gehandhabt, wie in jeder anderen Sprache die ich kenne (Java, C, C# usw. usf) auch: der Inhalt des rechts vom "="-Zeichen stehenden Bezeichners wird in den links vom "="-Zeichen stehenden Bezeichners übergeben. Beide Variablen, bzw. deine Liste namen und sortnamen *zeigen* dabei auf die selbe Speicheradresse in deinem RAM.
Das ist ein bisschen sehr verallgemeinert. Auch Java, C und C# erstellen Kopien, wenn es sich um Wertetypen handelt. Zb Strukturen in C, und mindestens mal primitive Datentypen bei allen. C++ hingegen macht mit seinen Standardcontainern sogar immer ein Kopie, weil es da explizite Referenztypen (und natürlich Pointer) gibt. Falls das also die “andere” Sprache des TEs ist, ist das überraschend. Genauso auch in PHP.
Astorek
User
Beiträge: 72
Registriert: Samstag 24. Januar 2009, 15:06
Kontaktdaten:

kbr hat geschrieben: Sonntag 1. Juli 2018, 10:24 @kruhling: Für das, was Du möchtest, gibt es die Funktion 'sorted'. Dann solltest Du berücksichtigen, dass 'Variablen' in Python tatsächlich stets Referenzen auf Objekte sind. So legt 'a = b' beispielsweise mit a eine zweite Referenz auf das Objekt an, welches bereits durch b referenziert wird. Wichtig für das weitere Verständnis ist die Unterscheidung von mutablen und immutablen Datentypen.
Wobei das (scheinbar? Bin auch nicht so tief drin in der Materie...) auch nicht bei allen Datentypen der Fall ist:

Code: Alles auswählen

>>> a = 5
>>> b = a
>>> a = 6
>>> a
6
>>> b
5
Bei Listen und Dictonaries ist der Fall hingegen eindeutig, da teilen sich idR. ein Speicherbereich zwei Variablennamen (oder mehr, falls man weitere verwendet und auf dieselbe Liste bzw. Dictionary zeigt). Hier muss man explizit die Liste bzw. Dictionary kopieren, ansonsten referenziert man nur auf ein- und denselben Speicherbereich. Eben mit den Beispielen, die ThomasL geschrieben hat...
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es ist so. 5 und 6 sind halt zwei verschiedene Objekte. Die jeweils unveränderlich sind, wobei das für die Betrachtung keine Rolle spielt. Denn dein Beispiel belegt nur, was kbr sagt: eine Zuweisung bedeutet nur einen Namen auf ein Objekt zeigen zu lassen. Du hast zwei Namen, die auf das gleiche Objekt zeigen, aber dann hängst du einen um.
Astorek
User
Beiträge: 72
Registriert: Samstag 24. Januar 2009, 15:06
Kontaktdaten:

__deets__ hat geschrieben: Sonntag 1. Juli 2018, 11:26 Es ist so. 5 und 6 sind halt zwei verschiedene Objekte. Die jeweils unveränderlich sind, wobei das für die Betrachtung keine Rolle spielt. Denn dein Beispiel belegt nur, was kbr sagt: eine Zuweisung bedeutet nur einen Namen auf ein Objekt zeigen zu lassen. Du hast zwei Namen, die auf das gleiche Objekt zeigen, aber dann hängst du einen um.
Ich bin ein Idiot. Danke, macht Sinn; mein Kopf ist heute wohl noch nicht vom Bett aufgestanden^^...
kruhling
User
Beiträge: 4
Registriert: Sonntag 31. Dezember 2017, 18:50

Hallo zusammen,
vielen Dank für eure vielen Antworten. Wenn nicht der Inhalt, sondern eine Referenz kopiert wird, erklärt das meine Frage und dann verstehe ich auch, warum das dann diesen Effekt hat. Ich danke euch.
Wie muss ich vorgehen, wenn ich jetzt wirklich eine Kopie anlegen will?
Danke.
Gruß, Kruhling
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Das hat ja ThomasL schon geschrieben. Aber ehrlich gesagt, braucht man viel seltener eine Kopie, als man nun am Anfang denken würde. Kopie braucht man ja nur, wenn man die Liste ändern will, aber statt eine Liste zu ändern, macht man normalerweise einfach eine neue Liste.
Tholo
User
Beiträge: 177
Registriert: Sonntag 7. Januar 2018, 20:36

@ThomasL
Wieso willst du ein Modul "Copy" importieren? Is doch alles dabei (zumindest weiß ich das bei Py3) was zum Listenkopieren benötigt wird.
Hab das grad nochmal probiert und es geht.Oder hab ich die Frage falsch verstanden?!?

Code: Alles auswählen

liste1 = [1,2,3]
liste2 = Liste1 #bei zeigen auf das gleiche Objekt
liste2.append(4) # neues Objekt mit 4 dazu
print("list1: ", liste1)
print("list2: ", liste2)
liste3 = liste1.copy() # neues Objekt, wie 1 wird kopiert
print("list3: ", liste3)

Code: Alles auswählen

list1:  [1, 2, 3]
list2:  [1, 2, 3, 4]
list3:  [1, 2, 3]
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Tholo: das gilt aber nur für die oberste Ebene. Für eine tiefe Kopie die auch Listen in Listen oder andere Datenstrukturen kopiert muss man tiefer in die Trickkiste greifen. Insbesondere wenn dann noch Rekursion dazu kommt. Da nimmt man besser copy.deepcopy.
Antworten