Beachten Sie, dass der Artikel "Über Python-Referenz" interessant war. In diesem Artikel,
Als ich mit Python anfing, stieß ich als erstes auf die mysteriöse Erklärung, die oft überall zu sehen ist: "Alle Python-Argumente werden als Referenz übergeben."
Es gab eine Passage. Wie bereits in den Kommentaren erwähnt, werden "alle Python-Argumente als Referenz übergeben", aber es scheint, dass es in Python keinen Wertübergang gibt! Ich habe einen Artikel "Übergeben von Wert, Übergeben von Referenz, Übergeben von Referenz" mit fast demselben Thema geschrieben, in dem Ganzzahlen und Gleitkommazahlen enthalten sind Ich habe geschrieben, dass die Zahl in Python als Wert übergeben wird. In der Tat gab das eine konsequente Erklärung und den Originalartikel
Wenn ein neues Objekt selbst einer Variablen zugewiesen wird, bezieht es sich auf den Ort, an dem das neue Objekt erstellt wurde, anstelle des vorherigen Referenzziels.
Dieser Teil ist der gleiche wie der, den ich in der Erklärung zum Übergeben von Referenzen nach Wert geschrieben habe. Ich habe mir jedoch die Kommentare angesehen und möglicherweise etwas Ungenaues geschrieben, sodass ich es eingehend untersucht habe.
Betrachten Sie den folgenden Python-Code.
ex1.py
a = 1
b = a
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)))
a : value = 1 id = 4360526320
b : value = 1 id = 4360526320
Dies ist sicherlich "Referenzübergabe", nicht "Wertübergabe". Denn wenn Sie einen Wert übergeben, sollte id (Zeigerwert) nicht wie das folgende C ++ übereinstimmen.
ex1.cpp
#include <iostream>
int main(){
int a = 1;
int b = a;
std::cout << "a : value = " << a << "\tid = " << &a << "\n";
std::cout << "b : value = " << b << "\tid = " << &b << "\n";
return 0;
}
a : value = 1 id = 0x7fff50360ae8
b : value = 1 id = 0x7fff50360ae4
Was ist, wenn dies als nächstes passiert?
ex2.py
a = 1
b = a
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)) + "\n")
b = 2
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)))
a : value = 1 id = 4348889584
b : value = 1 id = 4348889584
a : value = 1 id = 4348889584
b : value = 2 id = 4348889616
ex2.cpp
#include <iostream>
int main(){
int a = 1;
int b = a;
std::cout << "a : value = " << a << "\tid = " << &a << "\n";
std::cout << "b : value = " << b << "\tid = " << &b << "\n\n";
b = 2;
std::cout << "a : value = " << a << "\tid = " << &a << "\n";
std::cout << "b : value = " << b << "\tid = " << &b << "\n";
return 0;
}
a : value = 1 id = 0x7fff561cdae8
b : value = 1 id = 0x7fff561cdae4
a : value = 1 id = 0x7fff561cdae8
b : value = 2 id = 0x7fff561cdae4
Auf diese Weise ändert sich in Python im Gegensatz zu C ++ auch die ID, wenn Sie einen anderen Wert zuweisen. Mit anderen Worten, das Referenzziel ändert sich. Was ist mit zusammengesetzten Zuweisungen wie + =?
ex3.py
a = 1
b = a
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)) + "\n")
b += 2
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)))
a : value = 1 id = 4507830768
b : value = 1 id = 4507830768
a : value = 1 id = 4507830768
b : value = 3 id = 4507830832
Das ist das gleiche. Wie Sie im Kommentar des Originalartikels sehen können, heißt "b + = 2" tatsächlich "b = b + 2", und es wird auch eine neue Referenz zugewiesen. Mit anderen Worten, in Python: "Jedes Mal, wenn Sie den Wert einer Ganzzahl ändern, wird ein neues Objekt im Speicher erstellt und zugewiesen, sodass sich auch die ID ändert." Mit anderen Worten, in Python heißt es: "Sobald Sie eine Ganzzahl im Speicher generiert haben, können Sie sie nicht mehr ändern", was als "** unveränderlich " bezeichnet wird. Das Gegenteil ist " veränderlich **". Andere unveränderliche Typen sind Gleitkommazahlen, Bourians, Strings, Taples und None. Was in Python wichtig ist, ist "veränderlich oder nicht" und nicht "Übergeben von Werten". Es wird sein. Ich wusste es nicht.
Java hat übrigens etwas Ähnliches wie das obige Python-Beispiel. Wrapper-Klassen wie String und Integer und Double.
Ex1.java
class Ex1{
public static void main(String[] args){
String s1 = "foo";
String s2 = s1;
System.out.println("s1 : " + s1);
System.out.println("s2 : " + s2 + "\n");
s2 += "bar";
System.out.println("s1 : " + s1);
System.out.println("s2 : " + s2 + "\n");
Integer i1 = 1;
Integer i2 = i1;
System.out.println("i1 : " + i1);
System.out.println("i2 : " + i2 + "\n");
i2 += 2;
System.out.println("i1 : " + i1);
System.out.println("i2 : " + i2);
}
}
s1 : foo
s2 : foo
s1 : foo
s2 : foobar
i1 : 1
i2 : 1
i1 : 1
i2 : 3
Auf diese Weise verhalten sich Java-Zeichenfolgen und Ganzzahlen wie Referenzübergaben, obwohl sie Referenztypen sind. Versuchen wir, die Klassendatei zu dekompilieren, die durch Kompilieren der obigen Datei mit jad erstellt wurde.
Ex1.jad
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: Ex1.java
import java.io.PrintStream;
class Ex1
{
Ex1()
{
}
public static void main(String args[])
{
String s = "foo";
String s1 = s;
System.out.println((new StringBuilder()).append("s1 : ").append(s).toString());
System.out.println((new StringBuilder()).append("s2 : ").append(s1).append("\n").toString());
s1 = (new StringBuilder()).append(s1).append("bar").toString();
System.out.println((new StringBuilder()).append("s1 : ").append(s).toString());
System.out.println((new StringBuilder()).append("s2 : ").append(s1).append("\n").toString());
Integer integer = Integer.valueOf(1);
Integer integer1 = integer;
System.out.println((new StringBuilder()).append("i1 : ").append(integer).toString());
System.out.println((new StringBuilder()).append("i2 : ").append(integer1).append("\n").toString());
integer1 = Integer.valueOf(integer1.intValue() + 2);
System.out.println((new StringBuilder()).append("i1 : ").append(integer).toString());
System.out.println((new StringBuilder()).append("i2 : ").append(integer1).toString());
}
}
Es ist etwas schwer zu erkennen, aber beide werden durch zusammengesetzte Zuweisung neu geschrieben, um ein neues Objekt zu erstellen und das Referenzziel zu ändern. Als ich das noch nicht wusste, sagte ich: "Ich möchte mehrere Ints und Doubles in einer Methode zurückgeben, aber es ist mühsam, eine Klasse nur dafür zu erstellen, und Ints und Doubles können nur als Wert übergeben werden. Ich dachte: "Ist es nicht möglich, es als Argument zu führen?"
Um das oben Gesagte zusammenzufassen, schließen wir, dass ** unveränderliche Typen es Ihnen nicht erlauben, den Wert eines einmal erstellten Objekts zu ändern, sodass sich selbst das Übergeben als Referenz im Wesentlichen genauso verhält wie das Übergeben als Wert **. Werden. Entschuldigung.
Recommended Posts