In einigen Sprachen können Sie einen Parameter als Referenz oder Wert übergeben, indem Sie ein spezielles reserviertes Wort wie ref oder val verwenden . Wenn Sie einen Parameter an eine Python-Funktion übergeben, ändert sich der Wert des Parameters beim Verlassen der Funktion nie. Der einzige Weg, dies zu tun, ist die Verwendung des global reservierten Wortes (oder wie ich es derzeit verstehe).
Beispiel 1:
k = 2
def foo (n):
n = n * n #clarity regarding comment below
square = n
return square
j = foo(k)
print j
print k
würde zeigen
>>4
>>2
zeigt, dass k unverändert ist
In diesem Beispiel wird die Variable n niemals geändert
Beispiel 2:
n = 0
def foo():
global n
n = n * n
return n
In diesem Beispiel wird die Variable n geändert
Gibt es in Python eine Möglichkeit, eine Funktion aufzurufen und Python mitzuteilen, dass der Parameter entweder ein Wert oder ein Referenzparameter ist, anstatt global zu verwenden?
Zweitens heißt es in den Cambridge-Prüfungen der Stufe A jetzt, dass eine Funktion einen einzelnen Wert zurückgibt , während eine Prozedur mehr als einen Wert zurückgibt . Mir wurde beigebracht, dass eine Funktion in den 80er Jahren eine return-Anweisung hat und eine Prozedur nicht. Warum ist das jetzt falsch?
n
geändert werden sollte, verwenden Sie eine neue Variablesquare
, um das Ergebnis Ihrer Berechnung zu speichern.Antworten:
Sie können ein unveränderliches Objekt wie
str
odertuple
innerhalb einer Funktion in Python nicht ändern , aber Sie können Dinge tun wie:def foo(y): y[0] = y[0]**2 x = [5] foo(x) print x[0] # prints 25
Dies ist jedoch ein seltsamer Weg, es sei denn, Sie müssen immer bestimmte Elemente in einem Array quadrieren.
Beachten Sie, dass Sie in Python auch mehr als einen Wert zurückgeben können, wodurch einige Anwendungsfälle für die Referenzübergabe weniger wichtig sind:
def foo(x, y): return x**2, y**2 a = 2 b = 3 a, b = foo(a, b) # a == 4; b == 9
Wenn Sie solche Werte zurückgeben, werden sie als Tupel zurückgegeben, das wiederum entpackt wird.
Bearbeiten: Eine andere Möglichkeit, darüber nachzudenken, besteht darin, dass Sie in Python zwar keine expliziten Variablen als Referenz übergeben können, aber die Eigenschaften von übergebenen Objekten ändern können. In meinem Beispiel (und anderen) können Sie Mitglieder der Liste ändern Dies wurde übergeben. Sie können die übergebene Variable jedoch nicht vollständig neu zuweisen. Sehen Sie sich zum Beispiel an, wie die folgenden zwei Codeteile aussehen, als würden sie etwas Ähnliches tun, aber am Ende unterschiedliche Ergebnisse erzielen:
def clear_a(x): x = [] def clear_b(x): while x: x.pop() z = [1,2,3] clear_a(z) # z will not be changed clear_b(z) # z will be emptied
quelle
clear_a
erhält einen Verweis aufz
und speichert diesen Verweis inx
. Es ändert sich dann sofort, umx
auf ein anderes Array zu verweisen. Das ursprünglichez
Array wird im Rahmen von vergessenclear_a
, aber nicht geändert. Es bleibt unverändert, wenn Sie zum globalen Bereich zurückkehren.clear_b
Vergleichen Sie das , mit dem ein Verweis darauf erstelltz
und dann direkt darauf ausgeführt wird, ohne jemals ein neues Array zu erstellen oder auf andere Weise zu zeigenx
und etwas anderes.y = x
,y: y.pop()
und dann genanntclear_b(z)
, z immer noch leer ... Also wir brauchen etwas wiey = list(x)
eine Kopie von x (Liste (x) erklärt erstellen hier )run_thread = [True] t= threading.Thread(target=module2.some_method, \ args=(11,1,run_thread)) --do something - and when you want to sop run_thread[0] =False
Grundsätzlich gibt es drei Arten von Funktionsaufrufen:
Python ist eine Programmiersprache PASS-BY-OBJECT-REFERENCE.
Erstens ist es wichtig zu verstehen, dass eine Variable und der Wert der Variablen (des Objekts) zwei getrennte Dinge sind. Die Variable 'zeigt' auf das Objekt. Die Variable ist nicht das Objekt. Nochmal:
Die Variable ist nicht das Objekt
Beispiel: in der folgenden Codezeile:
>>> x = []
[]
ist die leere Liste,x
ist eine Variable, die auf die leere Liste verweist, aberx
selbst nicht die leere Liste ist.Betrachten Sie die Variable (
x
im obigen Fall) als Box und den Wert der Variablen ([]
) als Objekt innerhalb der Box.PASS BY OBJECT REFERENCE (Fall in Python):
Hier werden "Objektreferenzen als Wert übergeben."
def append_one(li): li.append(1) x = [0] append_one(x) print x
Hier erstellt die Anweisung
x = [0]
eine Variablex
(Box), die auf das Objekt zeigt[0]
.Bei der aufgerufenen Funktion wird eine neue Box
li
erstellt. Der Inhalt vonli
ist der gleiche wie der Inhalt der Boxx
. Beide Felder enthalten dasselbe Objekt. Das heißt, beide Variablen zeigen auf dasselbe Objekt im Speicher. Daher wird jede Änderung an dem Objekt, auf das von gezeigtli
wird, auch von dem Objekt reflektiert, auf das von gezeigt wirdx
.Zusammenfassend wird die Ausgabe des obigen Programms sein:
[0, 1]
Hinweis:
Wenn die Variable
li
in der Funktion neu zugewiesenli
wird, zeigt sie auf ein separates Objekt im Speicher.x
zeigt jedoch weiterhin auf dasselbe Objekt im Speicher, auf das zuvor verwiesen wurde.Beispiel:
def append_one(li): li = [0, 1] x = [0] append_one(x) print x
Die Ausgabe des Programms lautet:
[0]
PASS NACH REFERENZEN:
Die Box der aufrufenden Funktion wird an die aufgerufene Funktion weitergeleitet. Der Inhalt der Box (der Wert der Variablen) wird implizit an die aufgerufene Funktion übergeben. Daher wird jede Änderung des Inhalts der Box in der aufgerufenen Funktion in der aufrufenden Funktion wiedergegeben.
PASS BY VALUE:
In der aufgerufenen Funktion wird eine neue Box erstellt, und Kopien des Inhalts der Box aus der aufrufenden Funktion werden in den neuen Boxen gespeichert.
Hoffe das hilft.
quelle
OK, ich werde es versuchen. Python wird als Objektreferenz übergeben, was sich von dem unterscheidet, was Sie normalerweise als "nach Referenz" oder "nach Wert" betrachten. Nehmen Sie dieses Beispiel:
def foo(x): print x bar = 'some value' foo(bar)
Sie erstellen also ein Zeichenfolgenobjekt mit dem Wert 'some value' und "binden" es an eine Variable mit dem Namen
bar
. In C wäre das ähnlich wiebar
ein Zeiger auf 'einen Wert'.Wenn Sie anrufen
foo(bar)
, gehen Sie nicht anbar
sich vorbei. Sie übergebenbar
den Wert von ': einen Zeiger auf' einen Wert '. Zu diesem Zeitpunkt gibt es zwei "Zeiger" auf dasselbe Zeichenfolgenobjekt.Vergleichen Sie das jetzt mit:
def foo(x): x = 'another value' print x bar = 'some value' foo(bar)
Hier liegt der Unterschied. In der Schlange:
x = 'another value'
Sie ändern den Inhalt von nicht wirklich
x
. Das ist gar nicht möglich. Stattdessen erstellen Sie ein neues Zeichenfolgenobjekt mit dem Wert "Ein anderer Wert". Dieser Zuweisungsoperator? Es heißt nicht "überschreibe das Ding, auf dasx
es zeigt, mit dem neuen Wert". Es heißt "Updatex
, um stattdessen auf das neue Objekt zu zeigen". Nach dieser Zeile befinden sich zwei Zeichenfolgenobjekte: 'ein Wert' (mit dembar
Zeigen darauf) und 'ein anderer Wert' (mit demx
Zeigen darauf).Das ist nicht ungeschickt. Wenn Sie verstehen, wie es funktioniert, ist es ein wunderschön elegantes, effizientes System.
quelle
str
ings,tuple
s und andere Objekte unveränderlich sind . Wenn Sie ein veränderbares Objekt wie a übergebenlist
, können Sie es innerhalb der Funktion ändern, ohne es zurückgeben zu müssen, da alle Funktionsparameter Zeiger auf dieselben Objekte sind, die Sie übergeben haben.Hoffe, die folgende Beschreibung fasst es gut zusammen:
Hier sind zwei Dinge zu beachten - Variablen und Objekte.
Beispiel:
def changeval( myvar ): myvar = 20; print "values inside the function: ", myvar return myvar = 10; changeval( myvar ); print "values outside the function: ", myvar
O / P:
values inside the function: 20 values outside the function: 10
Beispiel:
def changelist( mylist ): mylist2=['a']; mylist.append(mylist2); print "values inside the function: ", mylist return mylist = [1,2,3]; changelist( mylist ); print "values outside the function: ", mylist
O / P:
values inside the function: [1, 2, 3, ['a']] values outside the function: [1, 2, 3, ['a']]
Beispiel:
def changelist( mylist ): mylist=['a']; print "values inside the function: ", mylist return mylist = [1,2,3]; changelist( mylist ); print "values outside the function: ", mylist
O / P:
values inside the function: ['a'] values outside the function: [1, 2, 3]
quelle
Python ist weder Pass-by-Value noch Pass-by-Reference. Es geht eher um "Objektreferenzen werden als Wert übergeben", wie hier beschrieben :
Hier ist, warum es nicht Wertübergabe ist. weil
def append(list): list.append(1) list = [0] reassign(list) append(list)
Gibt [0,1] zurück, was zeigt, dass eine Referenz eindeutig übergeben wurde, da die Übergabe des Werts es einer Funktion überhaupt nicht erlaubt, den übergeordneten Bereich zu ändern .
Sieht dann nach Pass-by-Reference aus, oder? Nee.
Hier ist, warum es nicht als Referenz übergeben wird. weil
def reassign(list): list = [0, 1] list = [0] reassign(list) print list
gibt [0] zurück und zeigt an, dass die ursprüngliche Referenz zerstört wurde, als die Liste neu zugewiesen wurde. Pass-by-Reference hätte [0,1] zurückgegeben .
Weitere Informationen finden Sie hier :
Wenn Sie möchten, dass Ihre Funktion nicht außerhalb des Bereichs manipuliert wird, müssen Sie eine Kopie der Eingabeparameter erstellen, mit denen ein neues Objekt erstellt wird.
from copy import copy def append(list): list2 = copy(list) list2.append(1) print list2 list = [0] append(list) print list
quelle
Technisch gesehen übergibt Python Argumente nicht nach Wert: alle nach Referenz. Aber ... da Python zwei Arten von Objekten hat: unveränderlich und veränderlich, passiert Folgendes:
Unveränderliche Argumente werden effektiv als Wert übergeben : Zeichenfolge, Ganzzahl und Tupel sind unveränderliche Objekttypen. Obwohl sie (wie alle Parameter) technisch "als Referenz übergeben" werden, sieht sie so aus, als ob sie als Wert übergeben würden, da Sie sie nicht direkt in der Funktion ändern können.
Veränderbare Argumente werden effektiv als Referenz übergeben : Listen oder Wörterbücher werden von ihren Zeigern übergeben. Jede direkte Änderung innerhalb der Funktion wie (Anhängen oder Löschen) wirkt sich auf das ursprüngliche Objekt aus.
So ist Python aufgebaut: Keine Kopien und alle werden als Referenz übergeben. Sie können eine Kopie explizit übergeben.
def sort(array): # do sort return array data = [1, 2, 3] sort(data[:]) # here you passed a copy
Letzter Punkt, den ich erwähnen möchte, ist, dass eine Funktion ihren eigenen Umfang hat.
def do_any_stuff_to_these_objects(a, b): a = a * 2 del b['last_name'] number = 1 # immutable hashmap = {'first_name' : 'john', 'last_name': 'legend'} # mutable do_any_stuff_to_these_objects(number, hashmap) print(number) # 1 , oh it should be 2 ! no a is changed inisde the function scope print(hashmap) # {'first_name': 'john'}
quelle
Dies ist also ein subtiler Punkt, denn während Python Variablen nur als Wert übergibt, ist jede Variable in Python eine Referenz. Wenn Sie Ihre Werte mit einem Funktionsaufruf ändern möchten, benötigen Sie ein veränderbares Objekt. Zum Beispiel:
l = [0] def set_3(x): x[0] = 3 set_3(l) print(l[0])
Im obigen Code ändert die Funktion den Inhalt eines List-Objekts (das veränderbar ist), sodass die Ausgabe 3 anstelle von 0 ist.
Ich schreibe diese Antwort nur, um zu veranschaulichen, was "nach Wert" in Python bedeutet. Der obige Code ist ein schlechter Stil, und wenn Sie Ihre Werte wirklich mutieren möchten, sollten Sie eine Klasse schreiben und Methoden innerhalb dieser Klasse aufrufen, wie MPX vorschlägt.
quelle
y = [a for a in x]; y[0] = 3; return y
x = foo(x)
.Die Antwort lautet
def set_4(x): y = [] for i in x: y.append(i) y[0] = 4 return y
und
l = [0] def set_3(x): x[0] = 3 set_3(l) print(l[0])
Das ist die beste Antwort, soweit es das tut, was es in der Frage sagt. Im Vergleich zu VB oder Pascal scheint dies jedoch sehr ungeschickt zu sein. Ist es die beste Methode, die wir haben?
Es ist nicht nur ungeschickt, es beinhaltet auch das manuelle Mutieren des ursprünglichen Parameters, z. B. durch Ändern des ursprünglichen Parameters in eine Liste: oder Kopieren in eine andere Liste, anstatt nur zu sagen: "Diesen Parameter als Wert verwenden" oder "Diesen verwenden" Als Referenz". Könnte die einfache Antwort sein, dass es dafür kein reserviertes Wort gibt, aber dies sind großartige Umgehungsmöglichkeiten?
quelle
Bedenken Sie, dass die Variable eine Box ist und der Wert, auf den sie zeigt, das "Ding" in der Box ist:
1. Als Referenz übergeben: Funktion teilt die gleiche Box und damit auch die Sache im Inneren.
2. Wert übergeben: Die Funktion erstellt eine neue Box, eine Replik der alten, einschließlich einer Kopie dessen, was sich darin befindet. Z.B. Java - Funktionen erstellen eine Kopie der Box und des darin enthaltenen Objekts, das sein kann: ein Grundelement / eine Referenz auf ein Objekt. (Beachten Sie, dass die kopierte Referenz in der neuen Box und das Original immer noch auf dasselbe Objekt verweisen. Hier ist die Referenz das Objekt in der Box, nicht das Objekt, auf das sie zeigt.)
3. Übergeben Sie die Objektreferenz : Die Funktion erstellt eine Box, enthält jedoch dasselbe, was die ursprüngliche Box eingeschlossen hat. Also in Python :
a) Wenn das Objekt in der Box veränderlich ist , werden die vorgenommenen Änderungen in der Originalbox wiedergegeben (z. B. Listen).
b) Wenn das Objekt unveränderlich ist (wie Python-Zeichenfolgen und numerische Typen), enthält das Feld in der Funktion dasselbe, bis Sie versuchen, seinen Wert zu ändern. Einmal geändert, ist die Sache in der Funktionsbox eine völlig neue Sache im Vergleich zur ursprünglichen. Daher gibt id () für dieses Feld jetzt die Identität des neuen Objekts an, das es enthält .
quelle
class demoClass: x = 4 y = 3 foo1 = demoClass() foo1.x = 2 foo2 = demoClass() foo2.y = 5 def mySquare(myObj): myObj.x = myObj.x**2 myObj.y = myObj.y**2 print('foo1.x =', foo1.x) print('foo1.y =', foo1.y) print('foo2.x =', foo2.x) print('foo2.y =', foo2.y) mySquare(foo1) mySquare(foo2) print('After square:') print('foo1.x =', foo1.x) print('foo1.y =', foo1.y) print('foo2.x =', foo2.x) print('foo2.y =', foo2.y)
quelle
In Python hat die Übergabe als Referenz oder als Wert mit den tatsächlichen Objekten zu tun, die Sie übergeben. Wenn Sie beispielsweise eine Liste übergeben, führen Sie diese Übergabe tatsächlich als Referenz durch, da die Liste ein veränderbares Objekt ist. Sie übergeben also einen Zeiger auf die Funktion und können das Objekt (die Liste) im Funktionskörper ändern.
Wenn Sie eine Zeichenfolge übergeben, erfolgt diese Übergabe nach Wert, sodass ein neues Zeichenfolgenobjekt erstellt und beim Beenden der Funktion zerstört wird. Es hat also alles mit veränderlichen und unveränderlichen Objekten zu tun.
quelle
Python ruft bereits per ref ..
Nehmen wir ein Beispiel:
def foo(var): print(hex(id(var))) x = 1 # any value print(hex(id(x))) # I think the id() give the ref... foo(x)
Ausgabe
0x50d43700 #with you might give another hex number deppend on your memory 0x50d43700
quelle
def foo(var): print(id(var)) var = 1234 print(id(var)) x = 123 print(id(x)) # I think the id() give the ref... foo(x) print(id(x))