Pytanie Jak przekazać zmienną przez odniesienie?


Dokumentacja Pythona wydaje się niejasna co do tego, czy parametry są przekazywane przez odniesienie czy wartość, a poniższy kod daje niezmienioną wartość "Oryginał"

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

Czy jest coś, co mogę zrobić, aby przekazać zmienną przez rzeczywiste odniesienie?


2055
2018-06-12 10:23


pochodzenie


Aby uzyskać krótkie wyjaśnienie / wyjaśnienie, patrz pierwsza odpowiedź to pytanie stackoverflow. Ponieważ łańcuchy są niezmienne, nie zostaną zmienione i zostanie utworzona nowa zmienna, a zatem zmienna "zewnętrzna" ma nadal tę samą wartość. - PhilS
Kod w odpowiedzi BlairConrad jest dobry, ale wyjaśnienie dostarczone przez DavidCournapeau i DarenThomas jest poprawne. - Ethan Furman
Zanim przeczytasz wybraną odpowiedź, rozważ przeczytanie tego krótkiego tekstu Inne języki mają "zmienne", Python ma "nazwy". Pomyśl o "nazwach" i "obiektach" zamiast "zmiennych" i "odniesieniach", a powinieneś unikać wielu podobnych problemów. - lqc
Dlaczego to niepotrzebnie używa klasy? To nie jest Java: P - Peter R
kolejnym sposobem obejścia tego problemu jest utworzenie takiego "odwołania", jak to: ref = type ('', (), {'n': 1}) stackoverflow.com/a/1123054/409638 - robert


Odpowiedzi:


Argumenty są przekazane przez zadanie. Uzasadnieniem tego jest dwojaki:

  1. parametr przekazany jest w rzeczywistości a odniesienie do obiektu (ale odniesienie jest przekazywane przez wartość)
  2. niektóre typy danych są zmienne, ale inne nie

Więc:

  • Jeśli zdasz zmienny obiekt do metody, metoda uzyskuje odwołanie do tego samego obiektu i możesz zmutować ją do rozkoszy twojego serca, ale jeśli ponownie powiążesz odniesienie w metodzie, zewnętrzny zasięg nic o tym nie wie i po tym, jak skończysz, zewnętrzne odniesienie będzie nadal wskazywało na oryginalny obiekt.

  • Jeśli zdasz niezmienny obiekt do metody, nadal nie można ponownie powiązać zewnętrznego odniesienia i nie można nawet zmutować obiektu.

Aby było jeszcze jaśniej, zróbmy kilka przykładów.

Lista - typ zmienny

Spróbujmy zmodyfikować listę, która została przekazana do metody:

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)

Wydajność:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

Ponieważ przekazany parametr jest odniesieniem do outer_list, a nie jego kopię, możemy użyć metod listy mutującej, aby ją zmienić i odzwierciedlić zmiany w zakresie zewnętrznym.

Zobaczmy teraz, co się stanie, gdy spróbujemy zmienić referencję, która została przekazana jako parametr:

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)

Wydajność:

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']

Od the_list parametr został przekazany przez wartość, przypisanie do niego nowej listy nie miało wpływu, jaki mógłby wykryć kod spoza metody. The the_list był kopią outer_list odniesienie i mieliśmy the_list wskaż nową listę, ale nie było sposobu na zmianę miejsca outer_list spiczasty.

String - niezmienny typ

Jest niezmienny, więc nic nie możemy zrobić, aby zmienić zawartość napisu

Teraz spróbujmy zmienić odniesienie

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)

Wydajność:

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

Ponownie, ponieważ the_string Parametr został przekazany przez wartość, przypisanie do niego nowego łańcucha nie miało wpływu, jaki mógłby wykryć kod spoza metody. The the_string był kopią outer_string odniesienie i mieliśmy the_string wskaż nowy ciąg, ale nie było sposobu, aby zmienić gdzie outer_string spiczasty.

Mam nadzieję, że to trochę wyjaśni.

EDYTOWAĆ: Zauważono, że nie odpowiada to na pytanie, które @ David najpierw zapytał: "Czy jest coś, co mogę zrobić, aby przekazać zmienną przez rzeczywiste odniesienie?". Pracujmy nad tym.

Jak sobie z tym poradzimy?

Jak pokazuje odpowiedź @ Andrea, możesz zwrócić nową wartość. Nie zmienia to sposobu, w jaki rzeczy są przekazywane, ale pozwala uzyskać informacje, które chcesz wycofać:

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)

Jeśli naprawdę chcesz uniknąć używania wartości zwracanej, możesz utworzyć klasę, która będzie przechowywać wartość i przekazać ją do funkcji lub użyć istniejącej klasy, takiej jak lista:

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])

Chociaż wydaje się to trochę uciążliwe.


2225
2018-06-12 11:18



Tak samo jest w C, kiedy przechodzisz "przez odniesienie", tak naprawdę przechodzisz według wartości odniesienie ... Zdefiniuj "przez odniesienie": P - Andrea Ambu
Nie jestem pewien, czy rozumiem twoje warunki. Przez jakiś czas byłem poza grą C, ale kiedy byłem w niej, nie było "przejścia przez referencję" - mogłeś przekazywać rzeczy, i zawsze było przekazywane przez wartość, więc to, co było na liście parametrów został skopiowany. Ale czasami rzecz była wskaźnikiem, który można było zastosować do fragmentu pamięci (prymitywny, tablica, struktura, cokolwiek), ale nie można było zmienić wskaźnika, który został skopiowany z zewnętrznego zakresu - kiedy skończyłeś z funkcją , oryginalny wskaźnik wciąż wskazywał ten sam adres. C ++ wprowadził odniesienia, które zachowywały się inaczej. - Blair Conrad
@Zac Bowling Nie rozumiem, jak to, co mówisz, ma znaczenie, w sensie praktycznym, dla tej odpowiedzi. Jeśli nowoprzybyły Python chciał wiedzieć o przekazywaniu przez ref / val, to na wynos z tej odpowiedzi jest: 1- ty mogą użyj odwołania, które funkcja otrzymuje jako swoje argumenty, aby zmodyfikować "zewnętrzną" wartość zmiennej, o ile nie zmienisz przypisania parametru, aby odnosić się do nowego obiektu. 2- Przypisanie do niezmiennego typu spowoduje zawsze utwórz nowy obiekt, który zrywa odwołanie do zmiennej zewnętrznej. - Cam Jackson
@ CamJackson, potrzebujesz lepszego przykładu - liczby są również niezmiennymi obiektami w Pythonie. Poza tym, nie byłoby prawdą, aby to powiedzieć każdy przypisanie bez indeksowania po lewej stronie równych spowoduje ponowne przypisanie nazwy do nowego obiektu, czy jest niezmienne czy nie? def Foo(alist): alist = [1,2,3]będzie nie modyfikować zawartość listy z perspektywy dzwoniących. - Mark Ransom
-1. Pokazany kod jest dobry, wyjaśnienie, w jaki sposób jest całkowicie błędny. Zobacz odpowiedzi DavidCournapeau lub DarenThomas, aby uzyskać prawidłowe wyjaśnienie, dlaczego. - Ethan Furman


Problem wynika z niezrozumienia zmiennych w Pythonie. Jeśli jesteś przyzwyczajony do większości tradycyjnych języków, masz umysłowy model tego, co dzieje się w następującej sekwencji:

a = 1
a = 2

Uważasz, że a to lokalizacja pamięci przechowująca wartość 1, następnie jest aktualizowany, aby zapisać wartość 2. To nie działa w Pythonie. Raczej, a rozpoczyna się jako odniesienie do obiektu z wartością 1, następnie zostaje ponownie przypisany jako odniesienie do obiektu z wartością 2. Te dwa przedmioty mogą nadal współistnieć a nie odnosi się już do pierwszego; w rzeczywistości mogą być dzielone przez dowolną liczbę innych odniesień w ramach programu.

Gdy wywołujesz funkcję z parametrem, tworzone jest nowe odniesienie, które odnosi się do przekazanego obiektu. Jest to oddzielne od odwołania użytego w wywołaniu funkcji, więc nie ma możliwości zaktualizowania tego odwołania i spowodowania, że ​​odnosi się ono do nowy obiekt. W twoim przykładzie:

def __init__(self):
    self.variable = 'Original'
    self.Change(self.variable)

def Change(self, var):
    var = 'Changed'

self.variable jest odniesieniem do obiektu typu string 'Original'. Kiedy zadzwonisz Change Tworzysz drugie odniesienie var do obiektu. Wewnątrz funkcji ponownie przypisujesz referencję var do innego obiektu typu string 'Changed', ale odniesienie self.variable jest oddzielny i nie zmienia się.

Jedynym sposobem obejścia tego jest przekazanie zmiennego obiektu. Ponieważ oba odwołania odnoszą się do tego samego obiektu, wszelkie zmiany obiektu są odzwierciedlane w obu miejscach.

def __init__(self):         
    self.variable = ['Original']
    self.Change(self.variable)

def Change(self, var):
    var[0] = 'Changed'

530
2017-11-15 17:45



Dobre, zwięzłe wyjaśnienie. Twój akapit "Kiedy wywołujesz funkcję ..." jest jednym z najlepszych wyjaśnień, jakie słyszałem o dość tajemniczym wyrażeniu, że "parametry funkcji Pythona są referencjami, przekazywane przez wartość". Myślę, że jeśli rozumiesz tylko ten akapit, wszystko inne ma tylko sens i płynie stąd jako logiczny wniosek. Następnie musisz mieć świadomość, kiedy tworzysz nowy obiekt i kiedy modyfikujesz istniejący. - Cam Jackson
Ale jak zmienić przypisanie? Myślałem, że nie możesz zmienić adresu "var", ale twój ciąg "Changed" będzie teraz przechowywany w adresie pamięci "var". Twój opis sprawia, że ​​wydaje się "Zmienione", a "Oryginalne" należą do różnych miejsc w pamięci, a Ty po prostu przełączasz "var" na inny adres. Czy to jest poprawne? - Glassjawed
@Glassjawed, myślę, że to rozumiesz. "Zmienione" i "Oryginalne" to dwa różne obiekty ciągów przy różnych adresach pamięci i zmiany "var" od wskazania do jednego do wskazania drugiego. - Mark Ransom
jest to najlepsze wytłumaczenie i powinno być zaakceptowaną odpowiedzią. Krótkie, zwięzłe i wyraźne. Inni wyznają nowe, mylące pojęcia, takie jak "referencja jest przekazywana przez wartość", "wywołanie obiektu" itp. Ta odpowiedź oczyszcza wszystko. Dzięki :) - ajay
użycie funkcji id () pomaga wyjaśnić sprawę, ponieważ wyjaśnia, kiedy Python tworzy nowy obiekt (tak myślę, tak czy inaczej). - Tim Richardson


Inne odpowiedzi były dość długie i skomplikowane, dlatego stworzyłem prosty diagram wyjaśniający sposób, w jaki Python traktuje zmienne i parametry. enter image description here


243
2017-09-04 16:05



Twój diagram dobrze wyjaśnia leżącą u podstaw koncepcję, chociaż nie nazywałbym innych odpowiedzi długi i skomplikowany. - Bruce Wayne
Bardzo eleganckie wyjaśnienie. Myślę, że inne odpowiedzi są również długie i skomplikowane. Dobra robota! - kirk.burleson
Nie ma znaczenia, czy A jest zmienne czy nie. Jeśli przypiszesz coś innego do B, A się nie zmienia. Jeśli obiekt jest zmienny, możesz go zmutować, oczywiście. Ale to nie ma nic wspólnego z przypisaniem bezpośrednio do nazwy. - Martijn Pieters♦
Dzięki za aktualizację, o wiele lepiej! Co dezorientuje większość ludzi jest przypisanie do subskrypcji; na przykład B[0] = 2, w przeciwieństwie do bezpośredniego przypisania, B = 2. - Martijn Pieters♦
"A jest przypisane do B." Czy to nie jest niejednoznaczne? Myślę, że w zwykłym angielskim może to oznaczać A=B lub B=A. - Hatshepsut


Nie jest to ani przekazywanie wartości, ani przekazywanie referencji - jest to wywołanie po obiekcie. Zobacz to, Fredrik Lundh:

http://effbot.org/zone/call-by-object.htm

Oto znaczący cytat:

"... zmienne [nazwy] są nie obiekty; nie mogą być oznaczone innymi zmiennymi ani określane przez obiekty. "

W twoim przykładzie, kiedy Change metoda nazywa się - a przestrzeń nazw jest dla niego stworzony; i var staje się nazwą w obrębie tej przestrzeni nazw dla obiektu typu string 'Original'. Ten obiekt ma wtedy nazwę w dwóch przestrzeniach nazw. Kolejny, var = 'Changed' wiąże var do nowego obiektu typu string, a tym samym zapomina o przestrzeni nazw metody 'Original'. Wreszcie, przestrzeń nazw jest zapomniana i ciąg znaków 'Changed' razem z tym.


220
2018-06-12 12:55



Ciężko mi kupić. Dla mnie jest tak samo jak Java, parametry są wskaźnikami do obiektów w pamięci, a te wskaźniki są przekazywane za pomocą stosu lub rejestrów. - Luciano
To nie jest jak java. Jednym z przypadków, w których nie jest on taki sam, są niezmienne obiekty. Pomyśl o banalnej funkcji lambda x: x. Zastosuj to dla x = [1, 2, 3] i x = (1, 2, 3). W pierwszym przypadku zwrócona wartość będzie kopią wejścia, a identyczna w drugim przypadku. - David Cournapeau
Nie to jest dokładnie jak semantyka Javy dla obiektów. Nie jestem pewien, co masz na myśli przez "W pierwszym przypadku zwrócona wartość będzie kopią danych wejściowych, a identyczna w drugim przypadku." ale to stwierdzenie wydaje się być całkowicie błędne. - Mike Graham
Jest dokładnie taki sam jak w Javie. Odniesienia do obiektów są przekazywane według wartości. Każdy, kto myśli inaczej, powinien dołączyć kod Pythona do a swap funkcja, która może zamienić dwa odwołania, na przykład: a = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42] - cayhorstmann
Jest dokładnie taki sam jak Java, gdy przekazujesz obiekty w Javie. Jednak Java ma także prymitywy, które są przekazywane przez kopiowanie wartości prymitywu. W związku z tym różnią się one w tym przypadku. - Claudiu


Pomyśl o rzeczach przekazywanych przez cesję zamiast przez odniesienie / według wartości. W ten sposób zawsze jest jasne, co się dzieje, o ile zrozumiesz, co dzieje się podczas normalnego zadania.

Tak więc, przekazując listę do funkcji / metody, lista jest przypisana do nazwy parametru. Dołączenie do listy spowoduje modyfikację listy. Ponowne przypisanie listy wewnątrz funkcja nie zmieni oryginalnej listy, ponieważ:

a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print a, b      # prints [1, 2, 3, 4] ['a', 'b']

Ponieważ nie można modyfikować typów niezmiennych, oni wydać się jak przekazywanie wartości - przekazywanie int do funkcji oznacza przypisanie int do parametru funkcji. Możesz tylko ponownie przypisać to, ale nie zmieni wartości zmiennych początkowych.


142
2018-06-12 12:17



Na pierwszy rzut oka ta odpowiedź wydaje się omijać oryginalne pytanie. Po drugim czytaniu zdałem sobie sprawę, że to czyni sprawę całkiem jasną. Dobrą kontynuację tego pojęcia "przypisania nazwy" można znaleźć tutaj: Code Like a Pythonista: Idiomatic Python - Christian Groleau


Effbot (znany również jako Fredrik Lundh) opisał zmienny styl przejścia Pythona jako wywołanie po obiekcie: http://effbot.org/zone/call-by-object.htm

Obiekty są przydzielane na stercie, a wskaźniki do nich mogą być przekazywane w dowolnym miejscu.

  • Kiedy wykonujesz zadanie takie jak x = 1000, tworzony jest wpis słownika, który odwzorowuje ciąg "x" w bieżącym obszarze nazw na wskaźnik do obiektu integer zawierającego tysiąc.

  • Po aktualizacji "x" przez x = 2000, tworzony jest nowy obiekt liczby całkowitej i słownik jest aktualizowany tak, aby wskazywał na nowy obiekt. Stary tysiąc obiektów pozostaje niezmieniony (i może lub nie może być żywy w zależności od tego, czy cokolwiek innego odnosi się do obiektu).

  • Kiedy wykonujesz nowe zadanie, takie jak y = x, tworzony jest nowy wpis słownika "y", który wskazuje ten sam obiekt co wpis "x".

  • Obiekty takie jak łańcuchy i liczby całkowite są niezmienny. Oznacza to po prostu, że nie istnieją metody, które mogą zmienić obiekt po jego utworzeniu. Na przykład, po utworzeniu obiektu całkowitego tysiąc, nigdy się nie zmieni. Matematyka jest wykonywana poprzez tworzenie nowych obiektów całkowitych.

  • Obiekty takie jak listy zmienny. Oznacza to, że zawartość obiektu może zostać zmieniona przez dowolne wskazanie obiektu. Na przykład, x = []; y = x; x.append(10); print y wydrukuje [10]. Utworzono pustą listę. Zarówno "x" jak i "y" wskazują tę samą listę. The dodać metoda mutuje (aktualizuje) obiekt listy (jak dodanie rekordu do bazy danych), a wynik jest widoczny zarówno dla "x", jak i "y" (tak jak aktualizacja bazy danych byłaby widoczna dla każdego połączenia z tą bazą danych).

Mam nadzieję, że wyjaśnisz tę kwestię za Ciebie.


53
2018-03-29 04:41



Naprawdę doceniam uczenie się o tym od programisty. Czy to prawda, że id() funkcja zwraca wartość wskaźnika (odwołania do obiektu), jak sugeruje sugestia pepr? - Honest Abe
@HonestAbe Tak, w CPython the ID() zwraca adres. Ale w innych pytony takich jak PyPy i Jython, ID() to po prostu unikalny identyfikator obiektu. - Raymond Hettinger
Inne odpowiedzi pozostawiły mnie oszołomionego i zdezorientowanego. Ten wyczyścił to wszystko. Dzięki. - shongololo
ta odpowiedź plus wskazówka do użycia id (), która pokazuje, kiedy przypisanie wiąże istniejącą nazwę z nowym obiektem, jest najlepsze w całym wątku. - Tim Richardson
Ta odpowiedź jest niewystarczająco zaaprobowana. - wandadars


Technicznie, Python zawsze używa przekazywania wartości referencyjnych. Powtarzam moja druga odpowiedź poprzeć moje oświadczenie.

Python zawsze używa wartości typu pass-by-reference. Nie ma żadnego wyjątku. Każde przypisanie zmiennej oznacza kopiowanie wartości odniesienia. Bez wyjątku. Każda zmienna jest nazwą związaną z wartością odniesienia. Zawsze.

Możesz myśleć o wartości odniesienia jako adres obiektu docelowego. Adres jest automatycznie dereferencjonowany, gdy jest używany. W ten sposób, pracując z wartością odniesienia, wydaje się, że pracujesz bezpośrednio z obiektem docelowym. Ale zawsze istnieje odniesienie pomiędzy krokiem, krok dalej, aby przeskoczyć do celu.

Oto przykład, który pokazuje, że Python używa przekazywania przez odniesienie:

Illustrated example of passing the argument

Jeśli argument został przekazany przez wartość, zewnętrzna lst nie można zmodyfikować. Zielone są obiektami docelowymi (czarny jest wartością przechowywaną wewnątrz, czerwony jest typem obiektu), żółty jest pamięcią z wartością odniesienia wewnątrz - narysowaną jako strzałka. Niebieska strzałka stała jest wartością odniesienia, która została przekazana do funkcji (za pomocą przerywanej niebieskiej strzałki). Brzydka ciemnożółta jest wewnętrznym słownikiem. (W rzeczywistości można go również narysować jako zieloną elipsę, a kolor i kształt mówią tylko, że jest wewnętrzny).

Możesz użyć id() wbudowana funkcja, aby dowiedzieć się, jaka jest wartość odniesienia (czyli adres obiektu docelowego).

W językach kompilowanych zmienną jest przestrzeń pamięci, która jest w stanie przechwycić wartość typu. W języku Python zmienna jest nazwą (przechwyconą wewnętrznie jako ciąg) związaną ze zmienną referencyjną, która przechowuje wartość odniesienia do obiektu docelowego. Nazwa zmiennej jest kluczem w słowniku wewnętrznym, część wartości tego elementu słownika przechowuje wartość odniesienia do celu.

Wartości referencyjne są ukryte w Pythonie. Nie ma żadnego jawnego typu użytkownika do przechowywania wartości odniesienia. Można jednak użyć elementu listy (lub elementu w dowolnym innym typie kontenera) jako zmiennej referencyjnej, ponieważ wszystkie kontenery przechowują te elementy również jako odniesienia do obiektów docelowych. Innymi słowy, elementy nie są zawarte w kontenerze - są tylko odniesienia do elementów.


53
2017-09-15 18:53



W rzeczywistości jest to potwierdzone przez podanie wartości referencyjnej. +1 dla tej odpowiedzi, chociaż przykład nie był dobry. - BugShotGG
Wymyślanie nowej terminologii (np. "Przekazywanie według wartości referencyjnej" lub "wywoływanie według obiektu" nie jest pomocne). "Call by (value | reference | name)" są terminami standardowymi. "odniesienie" jest terminem standardowym. Przekazywanie referencji według wartości dokładnie opisuje zachowanie Pythona, Javy i wielu innych języków przy użyciu standardowej terminologii. - cayhorstmann
@cayhorstmann: Problem polega na tym Zmienna Python nie ma takiego samego znaczenia terminologicznego jak w innych językach. Tą drogą, zadzwoń przez odniesienie tutaj nie pasuje. Poza tym, jak się masz dokładnie zdefiniuj termin odniesienie? Nieformalnie sposób Pythona można łatwo opisać jako przekazanie adresu obiektu. Ale nie pasuje do potencjalnie rozproszonej implementacji Pythona. - pepr
Podoba mi się ta odpowiedź, ale możesz rozważyć, czy ten przykład naprawdę pomaga lub szkodzi przepływowi. Ponadto, jeśli zastąpisz "wartość odniesienia" przez "odniesienie do obiektu", używałbyś terminologii, którą moglibyśmy uznać za "oficjalny", tak jak tutaj: Definiowanie funkcji - Honest Abe
Na końcu tego cytatu znajduje się przypis, który brzmi: "Tak właściwie, wywołanie przez odniesienie do obiektu byłby lepszym opisem, ponieważ jeśli przekazany zostanie zmienny obiekt, wywołujący zobaczy wszelkie zmiany dokonane przez wywoływacza ... " Zgadzam się z tobą, że zamieszanie spowodowane jest próbą dopasowania terminologii ustalonej z innymi językami. Semantyka na bok, rzeczy, które należy zrozumieć to: słowniki / przestrzenie nazw, operacja wiązania nazw oraz relację nazwy → wskaźnik → obiekt (jak już wiesz). - Honest Abe


Prostą sztuczką, której zwykle używam, jest po prostu umieszczenie jej na liście:

def Change(self, var):
    var[0] = 'Changed'

variable = ['Original']
self.Change(variable)      
print variable[0]

(Tak, wiem, że może to być niewygodne, ale czasami jest to dość proste).


36
2017-08-05 22:52



+1 dla małej ilości tekstu, co stanowi zasadnicze obejście problemu braku Pythona. (Jako kolejny komentarz / pytanie, które pasuje tutaj, jak również w dowolnym miejscu na tej stronie: Nie jest dla mnie jasne, dlaczego python nie może dostarczyć słowa kluczowego "ref" jak C #, które po prostu opakowuje argument rozmówcy na liście takich jak to i traktuj odwołania do argumentu w funkcji jako 0 element listy.) - M Katz
Miły. Aby przekazać przez referencję, zawiń w []. - Justas
Świetnie, dobrze zrobione, aby uniknąć całej pontyfikacji. - Puffin