Seite 1 von 1

Objektreferenzen Python

Verfasst: Donnerstag 11. Mai 2023, 18:29
von Pythonfan3000
Hallo liebe Community,

ich habe eine Frage bezüglich Objektreferenzen und dem kopieren von Objekten.
Und zwar steht in meinem Pythonbuch ungefähr folgendes:

Da Python gerne Ressourcen spart, kann es zu einem ungewöhnlichen Verhalten kommen. Wenn ein Objekt über eine Referenz einen Wert zugewiesen bekommt und auf denselben Wert bereits von einer anderen Referenz verwiesen wird, kann es passieren, dass anschließend beide Referenzen auf dasselbe Objekt verweisen. Dies geschieht, da Python Ressourcen sparen will.
Beispiel:

Code: Alles auswählen

x = 42
y = 56
print("f"x:{x}, y:{y}, identisch:{x is y}")

y = 42
print(f"x:{x}, y:{y}, identisch:{x is y}")
Die Ausgabe dieses Programmes lautet so:
x:42, y:56, identisch:False
x:42, y:42, identisch:True


Auf der Seite danach steht aber in meinem Buch ungefähr das hier:

Um eine echte Kopie von einem nicht einfachen Objekt wie Liste, Tupel, Dictionary, Set usw. zu erzeugen, muss man die Funktion deepcopy() nutzen oder man erstellt ein leeres Objekt und fügt anschließend alle Elemente einzeln hinzu.
Beispiel:

Code: Alles auswählen

import copy

x = [23, "hallo", -7.5]
y = []
for i in x:
	y.append(i)
print("dasselbe Objekt:", x is y)
print("gleicher Inhalt:", x == y)

x = [23, ["Berlin", "Hamburg"], -7.5, 12, 67]
y = copy.deepcopy(x)
print("dasselbe Objekt:", x is y)
print("gleicher Inhalt:", x == y)
Die Ausgabe dieses Programmes lautet folgendermaßen:
dasselbe Objekt:False
gleicher Inhalt: True

dasselbe Objekt:False
gleicher Inhalt:True


So. Jetzt zu meiner Frage. Wieso wird im ersten Programm am Ende ausgegeben, dass x und y auf dasselbe Objekt verweisen, aber bei dem zweiten Programm nicht? Denn nach der Zeile

Code: Alles auswählen

y.append(i)
hat x doch den gleichen Inhalt wie y. Also müssten beide Referenzen laut dem ersten Text auf das gleiche Objekt verweisen. Aber dies ist ja nicht der Fall, wie man der Ausgabe entnehmen kann.

Ich weiß, dass meine Frage vielleicht etwas kompliziert formuliert ist, aber ich habe versucht, es so gut zu erklären wie ich es eben kann. Das hier ist jetzt schon das zweite Forum, in dem ich diese Frage stelle und ich freue mich wirklich sehr über jede Antwort.

LG Pythonfan3000 :wink:

Re: Objektreferenzen Python

Verfasst: Freitag 12. Mai 2023, 02:50
von snafu
Pythonfan3000 hat geschrieben: Donnerstag 11. Mai 2023, 18:29 Wieso wird im ersten Programm am Ende ausgegeben, dass x und y auf dasselbe Objekt verweisen, aber bei dem zweiten Programm nicht?
Der Text spricht davon, dass die Wiederverwendung bestehender Objekte passieren *kann*. Das bedeutet nicht, dass dies immer der Fall wäre. Genau genommen gibt es den Effekt bei kleineren ganzen Zahlen (int) und bei Zeichenketten (str). Letzteres aber nur dann, wenn die Zeichenkette direkt angegeben wird. Bei zusammengesetzten Strings oder von Funktionen/Methoden erzeugten Strings greift die Wiederverwendung nicht. Hierzu ein Beispiel:

Code: Alles auswählen

"x" is "x"  # True
"x".upper() is "x".upper()  # False
"X" is "X"  # True
Wie du siehst, ist das Verhalten recht kompliziert und es muss auch nicht zwingend in der nächsten oder übernächsten Python-Version noch genau so sein. Nimm es einfach hin, dass es diese Optimierung gibt, aber verlasse dich nicht darauf. Gleichheit testet man mit dem ``==``-Operator, während man ``is`` nur sehr selten benötigt. Und dann sollte man auch genau wissen, was man tut.

Re: Objektreferenzen Python

Verfasst: Freitag 12. Mai 2023, 03:11
von __deets__
Das ist ein ziemlich esoterischer Fall, den das Buch da beschreibt. Und mit offensichtlich fatalen Konsequenzen für das Verständnis, wie deine Frage zeigt. Ganz allgemein gilt: Python versucht keine Optimierung bezüglich der objektidentität. Das wäre ein teurer und aufwendiger Prozess, mit fragwürdigen Vorteilen.

Was hier zu beobachten ist, ist einer von einer Reihe von Spezialfällen. Kleine Zahlen, sowie Strings, die Bezeichner darstellen, profitieren von einem solchen Optimierungsverhalten. Das ist aber nicht garantiert in der Sprachsemantik, und kann sich jederzeit undokumentiert ändern.

Darum vergiss dieses Kapitel. Es ist irrelevant, und verwirrend. Solltest du mal am Python Interpreter arbeiten, dann wird das anders. Aber bis dahin ist dann auch dieses Buch nicht mehr nötig.

Re: Objektreferenzen Python

Verfasst: Freitag 12. Mai 2023, 05:42
von snafu
Allein schon die Wiederverwendung einer Liste (wie im angeführten Beispiel) wäre fragwürdig. Denn sobald etwas angehangen wird, müsste das ja eine komplett neue Liste sein, damit die anderen Stellen, die noch von der alten Liste ausgehen, keine Überraschung erleben. Und wenn man sagen würde, dass append() immer eine neue Liste erzeugt, dann wäre das bei größeren Listen äußerst ineffizient, wenn da jedes Mal eine komplett neue Liste aufgebaut würde.

Daher arbeitet man mit Referenzen. Ein Objekt, welches du selbst erzeugt hast, kann mit mehreren Bezeichnern (Variablen) verbunden werden. Wenn du "a" änderst, dann ändert sich auch "b". Auch das überrascht viele Anfänger, ist jedoch ein vorhersehbareres Verhalten, sofern man es verstanden hat. Wenn du unabhängige Listen willst, die anfangs gleich sind, müsstest du halt nicht ``a = b`` schreiben, sondern beides Mal die gleichen Werte angeben oder das vom Buch erwähnte deepcopy() bzw. copy() verwenden (je nachdem, welcher Grad der "Unabhängigkeit" gewünscht ist).

Re: Objektreferenzen Python

Verfasst: Freitag 12. Mai 2023, 11:04
von kbr
@Pythonfan3000: In Python ist alles ein Objekt und diese werden über Referenzen angesprochen. In

Code: Alles auswählen

x = [23, "hallo", -7.5]
y = []
for i in x:
	y.append(i)

wird mit 'y = []' eine neue Liste angelegt also ein neues Objekt, und in diese anschließend die Inhalte der Liste x kopiert – aber nicht die Objekte selbst, sondern deren Referenzen. D. h. die Objekte 23, "hallo" und -7.5 gibt es nur einmal, dafür aber zwei verschiedene Listen mit Referenzen auf diese (Listen enthalten nur Referenzen).

Weiter unterscheidet Python zwischen mutablen und immutable Datentypen. Und das ist die eigentlich wichtige Information, und nicht irgendeine Speichereffizienz. Bei immutablen Datentypen ist die Zahl der Referenzen unerheblich, denn es kann zu keinen Seiteneffekten kommen. Bei mutable Datentypen ist das anders. Insofern ist das zweite Beispiel schlecht, denn es hört da auf, wo es eigentlich interessant wird und hinterlässt nur verwirrte Leser.