Die kurze Antwort lautet: Python führt immer einen Wert durch, aber jede Python-Variable ist tatsächlich ein Zeiger auf ein Objekt, sodass es manchmal wie ein Referenzübergang aussieht.
In Python ist jedes Objekt entweder veränderbar oder nicht veränderbar. Beispielsweise sind Listen, Dikte, Module und Pandas-Datenrahmen veränderbar, und Ints, Strings und Tupel sind nicht veränderbar. Veränderbare Objekte können intern geändert werden (z. B. ein Element zu einer Liste hinzufügen), nicht veränderbare Objekte jedoch nicht.
Wie ich zu Beginn sagte, können Sie sich jede Python-Variable als Zeiger auf ein Objekt vorstellen. Wenn Sie eine Variable an eine Funktion übergeben, ist die Variable (Zeiger) innerhalb der Funktion immer eine Kopie der übergebenen Variablen (Zeiger). Wenn Sie der internen Variablen also etwas Neues zuweisen, ändern Sie lediglich die lokale Variable, die auf ein anderes Objekt verweist. Dies ändert (mutiert) weder das ursprüngliche Objekt, auf das die Variable zeigte, noch lässt es die externe Variable auf das neue Objekt zeigen. Zu diesem Zeitpunkt zeigt die externe Variable weiterhin auf das ursprüngliche Objekt, die interne Variable jedoch auf ein neues Objekt.
Wenn Sie das ursprüngliche Objekt ändern möchten (nur mit veränderlichen Datentypen möglich), müssen Sie etwas tun, das das Objekt ändert, ohne der lokalen Variablen einen völlig neuen Wert zuzuweisen. Aus diesem Grund letgo()
und letgo3()
lassen Sie das externe Element unverändert, aber letgo2()
verändert es.
Wie @ursan betonte, würde bei letgo()
Verwendung von so etwas das ursprüngliche Objekt, df
auf das verwiesen wird, geändert (mutiert) , wodurch sich der über die globale a
Variable angezeigte Wert ändern würde :
def letgo(df):
df.drop('b', axis=1, inplace=True)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo(a)
In einigen Fällen können Sie die ursprüngliche Variable vollständig aushöhlen und mit neuen Daten füllen, ohne tatsächlich eine direkte Zuweisung vorzunehmen. Dies ändert beispielsweise das ursprüngliche Objekt, v
auf das verwiesen wird, und ändert die Daten, die bei einer v
späteren Verwendung angezeigt werden:
def letgo3(x):
x[:] = np.array([[3,3],[3,3]])
v = np.empty((2, 2))
letgo3(v)
Beachten Sie, dass ich etwas nicht direkt zuordne x
; Ich ordne dem gesamten internen Bereich von etwas zu x
.
Wenn Sie unbedingt ein völlig neues Objekt erstellen und extern sichtbar machen müssen (was manchmal bei Pandas der Fall ist), haben Sie zwei Möglichkeiten. Die 'saubere' Option wäre nur, das neue Objekt zurückzugeben, z.
def letgo(df):
df = df.drop('b',axis=1)
return df
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
a = letgo(a)
Eine andere Möglichkeit wäre, außerhalb Ihrer Funktion zu greifen und eine globale Variable direkt zu ändern. Dies ändert sich a
, um auf ein neues Objekt zu verweisen, und jede Funktion, die sich a
danach darauf bezieht, sieht dieses neue Objekt:
def letgo():
global a
a = a.drop('b',axis=1)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo()
Das direkte Ändern globaler Variablen ist normalerweise eine schlechte Idee, da jeder, der Ihren Code liest, Schwierigkeiten hat, herauszufinden, wie er a
geändert wurde. (Ich verwende im Allgemeinen globale Variablen für gemeinsam genutzte Parameter, die von vielen Funktionen in einem Skript verwendet werden, aber ich lasse nicht zu, dass sie diese globalen Variablen ändern.)