nbkr hat geschrieben:Das stimmt aber nicht bei Übergabe einer Variable an eine Funktion. Sonst würde die Änderungen die die Funktion vornimmt ja gleich auf die Variable durchschlagen.
Hi nbkr!
Der Unterschied ist nicht ob es eine Referenz zu einem Objekt ist, oder nicht, sondern ob der Variabletype
mutable (veränderbar) oder
immutable (unveränderbar) ist.
Und, JA --> Python arbeitet
immer mit Referenzen.
Bei Python sind gewisse Variabletypen veränderbar und gewisse nicht. Das ist genau definiert.
Nicht veränderbare Variabletypen können nur überschrieben, nicht verändert werden.
Nicht veränderbare Variabletypen sind:
- String
- Integer
- Long
- Tupel
Veränderbare Variabletypen sind:
- Liste
- Dictionary
Hier ein kleines Beispiel:
Wenn ich einer Variable einer Zahl zuweise, dann wird, falls diese Zahl noch nie verwendet wurde, dieser Zahl ein Speicherplatz zugewiesen und die Variable ist der Name zu diesem Speicherplatz.
Wenn ich die Zahl 5 zusätzlich einer anderen Variable zuweise, also noch einen Namen für die Zahl 5 vergebe, dann wird
kein neuer Speicherplatz für eine neue Zahl reserviert, sondern einfach nur der neue Name dem Speicherplatz für die Zahl 5 zugewiesen. (Man vergleiche die ID.)
Da bei nicht veränderbaren Datentypen immer auf den gleichen Speicherplatz verwiesen wird, darf der Inhalt des Speicherplatzes nicht mehr verändert werden, da ansonsten die Variablen (=Namen) plötzlich auf einen anderen Wert verweisen würden. Das ist bei nicht veränderbaren Datentypen nicht erwünscht.
Bei veränderbaren Datentypen verhält es sich komplett anders. Wird eine Variable einer Liste zugewiesen, dann wird
immer eine neue Liste erstellt, einem Speicherplatz zugewiesen und die Variable auf den neuen Speicherplatz verwiesen. Somit ist die Basis veränderbarer Variablen, einfach nur ein Speicherplatz, der sich nicht mit anderen überschneiden kann. Reicht später der Speicherplatz nicht mehr aus, dann wird einfach zusätzlicher Speicherplatz angefordert. Das passiert transparent im Hintergrund und ist für den Programmierer nicht wichtig.
Code: Alles auswählen
>>> liste_1 = []
>>> id(liste_1)
-1216406356
>>> liste_2 = []
>>> id(liste_2)
-1216406068
>>>
Wie man im Beispiel sieht, wird der zweiten Liste eine neue Speicheradresse zugewiesen.
Wird einer neuen Variable eine bereits existierende, unveränderliche Variable zugewiesen, dann wird der neuen Variable einfach nur der unveränderliche Wert (oder dessen Speicherbereich) zugewiesen. Beide Variablen, die alte und die neue, hängen nicht zusammen, sondern stellen beide eine Referenz zu einem unveränderlichen Wert dar. Es gibt keinen Unterschied, ob ich beiden Variablen beim Erstellen den Wert oder eine Variable zugewiesen habe. Beide sind im Ergebnis gleich --> je eine Variable zu einem unveränderlichen Wert. Wird im Nachhinein der alten Variable ein neuer Wert zugewiesen, dann ändert sich zwar der Wert und der Speicherbereich der alten Variable, die neue Variable ändert sich aber nicht, da sie ja per Definition auf eine unveränderliche Variable verweist.
Code: Alles auswählen
>>> a = 5
>>> b = a
>>> id(a)
134540408
>>> id(b)
134540408
>>> a = 10
>>> a
10
>>> b
5
>>> id(a)
134540348
>>> id(b)
134540408
>>>
Bei veränderlichen Datentypen muss man unterscheiden, ob eine Variable einen neuen Wert bekommt, also einem neuen Speicherbereich zugewiesen wird, oder ob der Inhalt des Speicherbereichs geändert wird. Das ändern des Inhalts des Speicherbereichs ist ja bei veränderbaren Datentypen erlaubt. Wird der Variable ein
neuer Speicherbereich zugewiesen, dann wird somit die Variable neu definiert, hat also keinen Bezug mehr zum alten Speicherbereich.
Code: Alles auswählen
>>> liste_1 = [10, 20]
>>> id(liste_1)
-1216406004
>>> liste_2 = liste_1
>>> id(liste_2)
-1216406004
>>> liste_1 = [30, 40]
>>> id(liste_1)
-1216405940
>>> id(liste_2)
-1216406004
>>> liste_1
[30, 40]
>>> liste_2
[10, 20]
In diesem Beispiel wird zuerst zwar der Variable "liste_2" der gleiche Speicherplatz wie der Variable "liste_1" zugewiesen, aber danach wird nicht der Wert des Speicherbereichs, sondern der Variable "liste_1" eine neue Liste, also ein neuer Speicherbereich, zugewiesen. Somit haben "liste_1" und "liste_2" keinen Bezug mehr zueinander.
Im nächsten Beispiel, wird zuerst der Variable "liste_2" der gleiche Speicherbplatz wie der Variable "liste_1" zugewiesen. Danach wird aber nur der Inhalt des Speicherbereichs verändert. Beide Variablen zeigen noch auf den selben Speicherbereich. Deshalb zeigen beide Variablen auch auf den selben Wert.
Code: Alles auswählen
>>> liste_1 = [10, 20]
>>> liste_2 = liste_1
>>> id(liste_1)
-1216406100
>>> id(liste_2)
-1216406100
>>> liste_1[0] = 30
>>> liste_1
[30, 20]
>>> liste_2
[30, 20]
>>> id(liste_1)
-1216406100
>>> id(liste_2)
-1216406100
>>>
Da also unveränderbare Datentypen per Definition nicht verändert werden können, kann man Variablen, die auf einen unveränderbaren Datentyp verweisen, immer nur überschreiben -- niemals verändern.
Auch wenn mehrere Variablen auf einen unveränderbaren Datentyp zeigen, ein Ändern einer dieser Variablen, weist dieser einen neuen Speicherbereich zu. Die anderen Variablen bleiben davon unbetroffen.
Auch wenn mehrere Variablen auf einen veränderbaren Datentyp zeigen, ein einzelnes Zuweisen eines neuen Speicherbereichs, einer dieser Variablen, wirkt sich nicht auf die anderen Variablen aus. Wird allerdings der Inhalt des Speicherbereichs verändert, dann wirkt sich das auf alle Variablen aus, die auf diesen Speicherbereich zeigen.
mfg
Gerold
PS: Weitere Lektüre:
http://www.python-forum.de/topic-5903.html