Argumente werden durch Zuweisung übergeben . Es gibt zwei Gründe dafür:
- Der übergebene Parameter ist tatsächlich eine Referenz auf ein Objekt (die Referenz wird jedoch als Wert übergeben).
- Einige Datentypen sind veränderbar, andere nicht
Damit:
Wenn Sie ein veränderbares Objekt an eine Methode übergeben, erhält die Methode einen Verweis auf dasselbe Objekt und Sie können es zur Freude Ihres Herzens mutieren. Wenn Sie jedoch den Verweis in der Methode erneut binden, weiß der äußere Bereich nichts darüber und danach Wenn Sie fertig sind, zeigt die äußere Referenz immer noch auf das ursprüngliche Objekt.
Wenn Sie ein unveränderliches Objekt an eine Methode übergeben, können Sie die äußere Referenz immer noch nicht erneut binden und das Objekt nicht einmal mutieren.
Um es noch deutlicher zu machen, lassen Sie uns einige Beispiele nennen.
Liste - ein veränderlicher Typ
Versuchen wir, die Liste zu ändern, die an eine Methode übergeben wurde:
def try_to_change_list_contents(the_list):
print('got', the_list)
the_list.append('four')
print('changed to', the_list)
outer_list = ['one', 'two', 'three']
print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)
Ausgabe:
before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']
Da der übergebene Parameter ein Verweis auf outer_list
und keine Kopie davon ist, können wir die Methoden der Mutationsliste verwenden, um ihn zu ändern und die Änderungen im äußeren Bereich wiederzugeben.
Nun wollen wir sehen, was passiert, wenn wir versuchen, die als Parameter übergebene Referenz zu ändern:
def try_to_change_list_reference(the_list):
print('got', the_list)
the_list = ['and', 'we', 'can', 'not', 'lie']
print('set to', the_list)
outer_list = ['we', 'like', 'proper', 'English']
print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)
Ausgabe:
before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']
Da der the_list
Parameter als Wert übergeben wurde, hatte das Zuweisen einer neuen Liste keine Auswirkung, die der Code außerhalb der Methode sehen konnte. Das the_list
war eine Kopie der outer_list
Referenz, und wir hatten the_list
auf eine neue Liste outer_list
verwiesen , aber es gab keine Möglichkeit zu ändern, wo darauf hingewiesen wurde.
String - ein unveränderlicher Typ
Es ist unveränderlich, daher können wir nichts tun, um den Inhalt der Zeichenfolge zu ändern
Versuchen wir nun, die Referenz zu ändern
def try_to_change_string_reference(the_string):
print('got', the_string)
the_string = 'In a kingdom by the sea'
print('set to', the_string)
outer_string = 'It was many and many a year ago'
print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)
Ausgabe:
before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago
Da der the_string
Parameter als Wert übergeben wurde, hatte das Zuweisen einer neuen Zeichenfolge keine Auswirkung, die der Code außerhalb der Methode sehen konnte. Das the_string
war eine Kopie der outer_string
Referenz, und wir hatten the_string
auf eine neue Zeichenfolge gezeigt, aber es gab keine Möglichkeit zu ändern, wo gezeigt wurde outer_string
.
Ich hoffe, das klärt die Dinge ein wenig auf.
BEARBEITEN: Es wurde festgestellt, dass dies nicht die Frage beantwortet, die @David ursprünglich gestellt hat: "Kann ich etwas tun, um die Variable als tatsächliche Referenz zu übergeben?". Lassen Sie uns daran arbeiten.
Wie kommen wir darum herum?
Wie die Antwort von @ Andrea zeigt, können Sie den neuen Wert zurückgeben. Dies ändert nichts an der Art und Weise, wie Dinge übergeben werden, aber Sie können die gewünschten Informationen wieder herausholen:
def return_a_whole_new_string(the_string):
new_string = something_to_do_with_the_old_string(the_string)
return new_string
# then you could call it like
my_string = return_a_whole_new_string(my_string)
Wenn Sie die Verwendung eines Rückgabewerts wirklich vermeiden möchten, können Sie eine Klasse erstellen, die Ihren Wert enthält, und ihn an die Funktion übergeben oder eine vorhandene Klasse wie eine Liste verwenden:
def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
new_string = something_to_do_with_the_old_string(stuff_to_change[0])
stuff_to_change[0] = new_string
# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)
do_something_with(wrapper[0])
Obwohl dies etwas umständlich erscheint.