Dokumentacja Pythona wydaje się niejasna, czy parametry są przekazywane przez odwołanie czy wartość, a poniższy kod generuje niezmienioną wartość „Original”
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 odwołanie?
python
reference
parameter-passing
pass-by-reference
David Sykes
źródło
źródło
Odpowiedzi:
Argumenty są przekazywane przez przypisanie . Uzasadnienie tego jest dwojakie:
Więc:
Jeśli przekażesz zmienny obiekt do metody, metoda otrzyma odwołanie do tego samego obiektu i możesz zmutować go ku uciesze twojego serca, ale jeśli ponownie powiążesz odniesienie w metodzie, zakres zewnętrzny nie będzie o tym nic wiedział, a po tym gdy skończysz, odniesienie zewnętrzne nadal będzie wskazywać na oryginalny obiekt.
Jeśli przekażesz niezmienny obiekt do metody, nadal nie możesz ponownie powiązać zewnętrznego odniesienia, a nawet nie możesz mutować obiektu.
Aby było jeszcze bardziej jasne, podajmy kilka przykładów.
Lista - typ zmienny
Spróbujmy zmodyfikować listę, która została przekazana do metody:
Wynik:
Ponieważ przekazany parametr jest odniesieniem do
outer_list
, a nie jego kopią, możemy użyć metod listy mutacji, aby go zmienić, a zmiany odzwierciedlić w zewnętrznym zakresie.Zobaczmy teraz, co się stanie, gdy spróbujemy zmienić odwołanie, które zostało przekazane jako parametr:
Wynik:
Ponieważ
the_list
parametr został przekazany przez wartość, przypisanie mu nowej listy nie miało żadnego wpływu na to, że kod poza metodą mógł zobaczyć.the_list
Była kopiaouter_list
odniesienia, i mieliśmythe_list
punkt do nowej listy, ale nie było sposobu, aby zmienić miejsceouter_list
spiczasty.String - niezmienny typ
Jest niezmienny, więc nie możemy nic zrobić, aby zmienić zawartość łańcucha
Teraz spróbujmy zmienić odniesienie
Wynik:
Ponownie, ponieważ
the_string
parametr został przekazany przez wartość, przypisanie do niego nowego ciągu nie wpłynęło na to, że kod poza metodą mógł zobaczyć.the_string
Była kopiaouter_string
odniesienia, i mieliśmythe_string
punkt do nowego łańcucha, ale nie było sposobu, aby zmienić miejsceouter_string
spiczasty.Mam nadzieję, że to trochę wyjaśni.
EDYCJA: Zauważono, że to nie odpowiada na pytanie, które @David pierwotnie zadał: „Czy jest coś, co mogę zrobić, aby przekazać zmienną przez faktyczne odwołanie?” Popracujmy nad tym.
Jak sobie z tym poradzić?
Jak pokazuje odpowiedź @ Andrei, możesz zwrócić nową wartość. Nie zmienia to sposobu przekazywania rzeczy, ale pozwala uzyskać informacje, które chcesz odzyskać:
Jeśli naprawdę chcesz uniknąć używania wartości zwracanej, możesz utworzyć klasę, która będzie przechowywać twoją wartość i przekaże ją do funkcji lub użyj istniejącej klasy, takiej jak lista:
Chociaż wydaje się to trochę kłopotliwe.
źródło
def Foo(alist): alist = [1,2,3]
będzie nie modyfikować zawartość listy z punktu widzenia rozmówców.Problem wynika z niezrozumienia, jakie zmienne są w Pythonie. Jeśli jesteś przyzwyczajony do większości tradycyjnych języków, masz mentalny model tego, co dzieje się w następującej kolejności:
Uważasz, że
a
jest to miejsce w pamięci, które przechowuje wartość1
, a następnie jest aktualizowane w celu zapisania wartości2
. Nie tak to działa w Pythonie. Zamiast tegoa
zaczyna się jako odwołanie do obiektu o wartości1
, a następnie zostaje ponownie przypisane jako odwołanie do obiektu o wartości2
. Te dwa obiekty mogą nadal współistnieć, mimo żea
nie odnoszą się już do pierwszego; w rzeczywistości mogą być one udostępniane przez dowolną liczbę innych odniesień w programie.Kiedy wywołujesz funkcję z parametrem, tworzone jest nowe odwołanie, które odnosi się do przekazanego obiektu. Jest to oddzielne od odwołania, które zostało użyte w wywołaniu funkcji, więc nie ma sposobu, aby zaktualizować to odniesienie i sprawić, by odnosiło się do nowy obiekt W twoim przykładzie:
self.variable
jest odwołaniem do obiektu ciągu'Original'
. Kiedy dzwoniszChange
, tworzysz drugie odniesienievar
do obiektu. Wewnątrz funkcji ponownie przypisujesz odwołanievar
do innego obiektu łańcuchowego'Changed'
, ale odwołanieself.variable
jest osobne i nie zmienia się.Jedynym sposobem na obejście tego jest ominięcie zmiennego obiektu. Ponieważ oba odwołania odnoszą się do tego samego obiektu, wszelkie zmiany obiektu są odzwierciedlane w obu miejscach.
źródło
Znalazłem inne odpowiedzi raczej długie i skomplikowane, dlatego stworzyłem ten prosty schemat, aby wyjaśnić sposób, w jaki Python traktuje zmienne i parametry.
źródło
B[0] = 2
, w porównaniu z bezpośrednim przypisaniuB = 2
.A=B
alboB=A
.Nie jest on ani przekazywany przez wartość, ani przekazywany przez referencję - jest to wywołanie obiektu. Zobacz to, autorstwa Fredrika Lundha:
http://effbot.org/zone/call-by-object.htm
Oto znaczący cytat:
W twoim przykładzie, gdy
Change
wywoływana jest metoda - tworzona jest dla niej przestrzeń nazw ; ivar
staje się nazwą w obrębie przestrzeni nazw dla obiektu typu string'Original'
. Ten obiekt ma następnie nazwę w dwóch przestrzeniach nazw. Następnievar = 'Changed'
wiążevar
się z nowym obiektem łańcuchowym, dlatego przestrzeń nazw metody zapomina'Original'
. Wreszcie przestrzeń nazw zostaje zapomniana, a ciąg'Changed'
wraz z nią.źródło
swap
funkcji, która może zamienić dwie referencje, w ten sposób:a = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42]
Pomyśl o przekazywaniu rzeczy przez przypisanie zamiast przez referencję / wartość. W ten sposób zawsze jest jasne, co się dzieje, dopóki rozumiesz, co dzieje się podczas normalnego zadania.
Tak więc, gdy przekazujemy listę do funkcji / metody, lista jest przypisywana do nazwy parametru. Dołączenie do listy spowoduje modyfikację listy. Ponowne przypisanie listy wewnątrz funkcji nie zmieni oryginalnej listy, ponieważ:
Ponieważ typy niezmienne nie mogą być modyfikowane, wydają się są przekazywane przez wartość - przekazanie int do funkcji oznacza przypisanie int do parametru funkcji. Możesz tylko to zmienić, ale nie zmieni to oryginalnej wartości zmiennych.
źródło
Effbot (znany również jako Fredrik Lundh) opisał zmienny styl przekazywania Pythona jako call-by-object: http://effbot.org/zone/call-by-object.htm
Obiekty są przydzielane na stercie, a wskaźniki do nich można przekazywać w dowolnym miejscu.
Podczas wykonywania przypisania, takiego jak
x = 1000
, tworzony jest wpis słownika, który odwzorowuje ciąg „x” w bieżącej przestrzeni nazw na wskaźnik na obiekt liczb całkowitych zawierający tysiąc.Po zaktualizowaniu „x” za pomocą
x = 2000
, tworzony jest nowy obiekt liczb całkowitych, a słownik jest aktualizowany, aby wskazywał na nowy obiekt. Stary tysiąc obiektów pozostaje niezmieniony (i może być żywy, w zależności od tego, czy coś jeszcze odnosi się do obiektu).Kiedy wykonujesz nowe przypisanie, takie jak
y = x
, tworzony jest nowy wpis słownika „y”, który wskazuje ten sam obiekt co wpis dla „x”.Obiekty takie jak łańcuchy i liczby całkowite są niezmienne . Oznacza to po prostu, że nie ma metod, które mogłyby zmienić obiekt po jego utworzeniu. Na przykład, gdy zostanie utworzony obiekt liczby całkowitej tysiąc, nigdy się nie zmieni. Matematyka odbywa się poprzez tworzenie nowych obiektów całkowitych.
Obiekty takie jak listy można modyfikować . Oznacza to, że zawartość obiektu można zmienić przez cokolwiek, co wskazuje na obiekt. Na przykład
x = []; y = x; x.append(10); print y
wydrukuje[10]
. Pusta lista została utworzona. Zarówno „x”, jak i „y” wskazują na tę samą listę. Metoda Append 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 to wyjaśni ci problem.
źródło
id()
funkcja zwraca wartość wskaźnika (odwołania do obiektu), jak sugeruje odpowiedź pepr?Technicznie, Python zawsze używa wartości referencyjnych pass by . Powtórzę moją drugą odpowiedź na poparcie mojego oświadczenia.
Python zawsze używa wartości przekazywanych przez referencje. Nie ma żadnego wyjątku. Każde przypisanie zmiennej oznacza skopiowanie 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 adresie obiektu docelowego. Adres jest automatycznie usuwany z listy przy użyciu. W ten sposób, pracując z wartością odniesienia, wydaje się, że pracujesz bezpośrednio z obiektem docelowym. Ale pomiędzy nimi zawsze jest odniesienie, jeszcze jeden krok, aby przejść do celu.
Oto przykład, który dowodzi, że Python używa przekazywania przez referencję:
Jeśli argument został przekazany przez wartość,
lst
nie można zmienić wartości zewnętrznej . Zielony to obiekty docelowe (czarny to wartość przechowywana w środku, czerwony to typ obiektu), żółty to pamięć z wartością odniesienia w środku - narysowaną jako strzałka. Niebieska stała strzałka to wartość odniesienia, która została przekazana do funkcji (za pomocą przerywanej ścieżki niebieskiej strzałki). Brzydka ciemnożółta to wewnętrzny słownik. (W rzeczywistości można go narysować również jako zieloną elipsę. Kolor i kształt mówi tylko, że jest wewnętrzny).Za pomocą
id()
wbudowanej funkcji można dowiedzieć się, co to jest wartość odniesienia (to znaczy adres obiektu docelowego).W skompilowanych językach zmienna to przestrzeń pamięci, która jest w stanie uchwycić wartość typu. W Pythonie zmienna jest nazwą (przechwyconą wewnętrznie jako ciąg) powiązaną ze zmienną referencyjną, która przechowuje wartość referencyjną do obiektu docelowego. Nazwa zmiennej jest kluczem w wewnętrznym słowniku, 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 odpowiednim typie kontenera) jako zmiennej referencyjnej, ponieważ wszystkie kontenery przechowują elementy również jako referencje do obiektów docelowych. Innymi słowy, elementy faktycznie nie są zawarte w kontenerze - są tylko odniesienia do elementów.
źródło
W Pythonie nie ma żadnych zmiennych
Kluczem do zrozumienia przekazywania parametrów jest zaprzestanie myślenia o „zmiennych”. W Pythonie znajdują się nazwy i obiekty, które razem wyglądają jak zmienne, ale zawsze warto rozróżnić trzy.
To wszystko. Zmienność nie ma znaczenia dla tego pytania.
Przykład:
Wiąże to nazwę
a
z obiektem typu liczba całkowita, który zawiera wartość 1.To wiąże nazwę
b
z tym samym obiektem, z którym nazwax
jest obecnie związana. Potem nazwab
nie ma już z nią nic wspólnegox
.Zobacz sekcje 3.1 i 4.2 w dokumentacji języka Python 3.
Jak przeczytać przykład w pytaniu
W kodzie pokazanym w pytaniu instrukcja
self.Change(self.variable)
wiąże nazwęvar
(w zakresie funkcjiChange
) z obiektem, który przechowuje wartość'Original'
i przypisanievar = 'Changed'
(w treści funkcjiChange
) ponownie przypisuje tę samą nazwę: do innego obiektu (co się dzieje do trzymania sznurka, ale mogło to być coś zupełnie innego).Jak przekazać przez odniesienie
Jeśli więc rzeczą, którą chcesz zmienić, jest obiekt zmienny, nie ma problemu, ponieważ wszystko jest skutecznie przekazywane przez referencję.
Jeśli jest to obiekt niezmienny (np. Bool, liczba, łańcuch), sposobem jest zawinięcie go w obiekt zmienny.
Szybkim i brudnym rozwiązaniem tego jest lista jednoelementowa (zamiast
self.variable
pass[self.variable]
i w funkcji modyfikacjivar[0]
).Bardziej pythonowym podejściem byłoby wprowadzenie trywialnej klasy z jednym atrybutem. Funkcja odbiera instancję klasy i manipuluje atrybutem.
źródło
int
deklaruje zmienną, aleInteger
nie. Obie deklarują zmienne.Integer
Zmienna jest przedmiotem,int
zmienna jest prymitywne. Jako przykład zademonstrowałeś działanie swoich zmiennych, pokazująca = 1; b = a; a++ # doesn't modify b
. Dotyczy to również Pythona (używając,+= 1
ponieważ nie ma go++
w Pythonie)!Prostą sztuczką, której zwykle używam, jest po prostu zawinięcie jej w listę:
(Tak, wiem, że może to być niewygodne, ale czasami wystarczy to zrobić.)
źródło
(edytuj - Blair zaktualizował swoją niezwykle popularną odpowiedź, aby była teraz dokładna)
Myślę, że należy zauważyć, że obecny post z największą liczbą głosów (autor: Blair Conrad), choć jest poprawny pod względem wyniku, wprowadza w błąd i jest niepoprawny na podstawie jego definicji. Chociaż istnieje wiele języków (takich jak C), które pozwalają użytkownikowi przejść przez referencję lub przekazać wartość, Python nie jest jednym z nich.
Odpowiedź Davida Cournapeau wskazuje na prawdziwą odpowiedź i wyjaśnia, dlaczego zachowanie w poście Blaira Conrada wydaje się poprawne, a definicje nie.
W zakresie, w jakim Python jest przekazywany według wartości, wszystkie języki są przekazywane według wartości, ponieważ należy wysłać część danych (czy to „wartość”, czy „referencję”). Nie oznacza to jednak, że Python przekazuje wartość w tym sensie, że programista C by o tym pomyślał.
Jeśli chcesz tego zachowania, odpowiedź Blair Conrad jest w porządku. Ale jeśli chcesz wiedzieć, dlaczego Python nie jest ani przekazywany przez wartość, ani przekazywany przez odniesienie, przeczytaj odpowiedź Davida Cournapeau.
źródło
void swap(int& x, int& y) { int temp = x; x = y; y = temp; }
zamieni przekazane do niego zmienne. W Pascal używaszvar
zamiast&
.Masz tutaj naprawdę dobre odpowiedzi.
źródło
W tym przypadku zmienna nazwana
var
w metodzieChange
jest przypisana do odwołaniaself.variable
i natychmiast przypisujesz ciągvar
. To już nie wskazujeself.variable
. Poniżej przedstawiono fragment kodu, co by się stało, gdyby zmodyfikować strukturę danych wskazywanego przezvar
iself.variable
, w tym przypadku listy:Jestem pewien, że ktoś inny mógłby to wyjaśnić.
źródło
Schemat przekazywania przez Pythona nie jest dokładnie taki sam jak opcja parametrów referencyjnych C ++, ale okazuje się być bardzo podobny do modelu przekazywania argumentów języka C (i innych) w praktyce:
źródło
Jak możesz powiedzieć, musisz mieć zmienny obiekt, ale pozwól, że zasugeruję ci sprawdzenie zmiennych globalnych, ponieważ mogą ci pomóc, a nawet rozwiązać ten problem!
http://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
przykład:
źródło
Wiele spostrzeżeń w odpowiedziach tutaj, ale myślę, że dodatkowa kwestia nie jest tutaj wyraźnie wymieniona. Cytowanie z dokumentacji Pythona https://docs.python.org/2/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
„W Pythonie zmienne, do których istnieją odwołania tylko w obrębie funkcji, są domyślnie globalne. Jeśli zmiennej przypisano nową wartość w dowolnym miejscu w ciele funkcji, zakłada się, że jest ona lokalna. Jeśli zmienna kiedykolwiek zostanie przypisana nowej wartości w funkcji, zmienna jest domyślnie lokalna i musisz jawnie zadeklarować ją jako „globalną”. Choć na początku jest to nieco zaskakujące, wyjaśnienie to wyjaśnia. Z jednej strony wymaganie globalne dla przypisanych zmiennych zapewnia ochronę przed niezamierzonymi skutkami ubocznymi. z drugiej strony, jeśli globalny byłby wymagany dla wszystkich globalnych odniesień, cały czas używałbyś globalnego. Musiałbyś zadeklarować jako globalny każde odniesienie do wbudowanej funkcji lub komponentu importowanego modułu. Ten bałagan pokonałby przydatność globalnej deklaracji do identyfikowania skutków ubocznych. ”
Nawet w przypadku przekazania zmiennego obiektu do funkcji nadal obowiązuje. I dla mnie jasno wyjaśnia przyczynę różnicy w zachowaniu między przypisaniem do obiektu a działaniem na obiekcie w funkcji.
daje:
Przypisanie do zmiennej globalnej, która nie jest zadeklarowana jako globalna, tworzy zatem nowy obiekt lokalny i przerywa połączenie z pierwotnym obiektem.
źródło
Oto proste (mam nadzieję) wyjaśnienie pojęcia
pass by object
zastosowanego w Pythonie.Ilekroć przekazujesz obiekt do funkcji, sam obiekt jest przekazywany (obiekt w Pythonie jest tak naprawdę, jak nazwałbyś wartość w innych językach programowania), a nie odniesienie do tego obiektu. Innymi słowy, kiedy dzwonisz:
Rzeczywisty obiekt - [0, 1] (który byłby nazywany wartością w innych językach programowania) jest przekazywany. W rzeczywistości funkcja
change_me
będzie próbowała zrobić coś takiego:co oczywiście nie zmieni obiektu przekazanego do funkcji. Jeśli funkcja wyglądała tak:
Wówczas połączenie spowodowałoby:
co oczywiście zmieni obiekt. Ta odpowiedź dobrze to wyjaśnia.
źródło
list = [1, 2, 3]
przyczyny ponownego wykorzystanialist
nazwy do czegoś innego i forgeting pierwotnie przekazany obiekt. Możesz jednak spróbowaćlist[:] = [1, 2, 3]
(nawiasem mówiąc,list
jest to niepoprawna nazwa zmiennej. Myślenie o tym[0, 1] = [1, 2, 3]
jest kompletnym nonsensem. W każdym razie, co według ciebie oznacza, że obiekt jest przekazywany ? Co Twoim zdaniem jest kopiowane do funkcji?[0, 1] = [1, 2, 3]
to po prostu zły przykład. W Pythonie nie ma nic takiego.alist[2]
liczy się jako nazwa trzeciego elementu alist. Ale myślę, że źle zrozumiałem na czym polegał twój problem. :-)Oprócz wszystkich świetnych wyjaśnień dotyczących tego, jak działają te rzeczy w Pythonie, nie widzę prostej sugestii dotyczącej problemu. Gdy wydaje się, że tworzysz obiekty i instancje, pythoniczny sposób obsługi zmiennych instancji i ich zmiany jest następujący:
W metodach instancji zwykle odnosi się
self
do atrybutów instancji dostępu. Normalne jest ustawianie atrybutów instancji__init__
i odczytywanie lub zmienianie ich w metodach instancji. Dlatego przekazujeszself
również pierwszy argumentdef Change
.Innym rozwiązaniem byłoby stworzenie metody statycznej takiej jak ta:
źródło
Istnieje pewna sztuczka, aby przekazać obiekt przez referencję, nawet jeśli język nie pozwala. Działa również w Javie, jest to lista z jednym elementem. ;-)
To brzydki hack, ale działa. ;-P
źródło
p
jest odwołaniem do zmiennego obiektu listy, który z kolei przechowuje obiektobj
. Zostanie przekazane odniesienie „p”changeRef
. WewnątrzchangeRef
tworzone jest nowe odwołanie (nazywane jest nowym odwołaniemref
), które wskazuje ten sam obiekt listy, któryp
wskazuje. Ale ponieważ listy można modyfikować, zmiany na liście są widoczne w obu odnośnikach. W takim przypadkuref
odwołanie zostało użyte do zmiany obiektu o indeksie 0, aby następnie przechowałPassByReference('Michael')
obiekt. Zmiana obiektu listy została wykonana za pomocą,ref
ale ta zmiana jest widoczna dlap
.p
iref
punkt do obiektu listy, która przechowuje jeden obiekt,PassByReference('Michael')
. Wynika z tego, żep[0].name
powracaMichael
. Oczywiście,ref
teraz wyszedł poza zakres i może być zbierany śmieci, ale mimo wszystko.name
, oryginalnegoPassByReference
obiektu związanego z odniesieniemobj
, choć. W rzeczywistościobj.name
wróciPeter
. Powyższe komentarze zakładają, że podana definicjaMark Ransom
.PassByReference
obiekt innymPassByReference
obiektem na liście i odniosłeś się do drugiego z dwóch obiektów.Zastosowałem następującą metodę, aby szybko przekonwertować kilka kodów Fortran na Python. To prawda, że nie jest przekazywane przez odniesienie, jak postawiono oryginalne pytanie, ale w niektórych przypadkach jest to proste obejście.
źródło
dict
a następnie zwracadict
. Jednak podczas czyszczenia może się okazać, że konieczna jest przebudowa części systemu. Dlatego funkcja musi nie tylko zwrócić wyczyszczone,dict
ale także być w stanie zasygnalizować odbudowę. Próbowałem przekazaćbool
referencję, ale ofc to nie działa. Zastanawiając się, jak to rozwiązać, znalazłem twoje rozwiązanie (w zasadzie zwracanie krotki), które działa najlepiej, a jednocześnie nie jest hack / obejściem w ogóle (IMHO).Chociaż przekazywanie przez odniesienie nie jest niczym, co dobrze pasuje do pytona i powinno być rzadko stosowane, istnieją pewne obejścia, które faktycznie mogą działać, aby obiekt został aktualnie przypisany do zmiennej lokalnej lub nawet przypisać zmienną lokalną z wnętrza wywoływanej funkcji.
Podstawową ideą jest posiadanie funkcji, która może uzyskać dostęp i może być przekazywana jako obiekt do innych funkcji lub przechowywana w klasie.
Jednym ze sposobów jest użycie
global
(dla zmiennych globalnych) lubnonlocal
(dla zmiennych lokalnych w funkcji) w funkcji otoki.Ten sam pomysł działa na odczytywanie i
del
etowanie zmiennej.Do samego odczytu istnieje jeszcze krótszy sposób użycia,
lambda: x
który zwraca wywołanie, które po wywołaniu zwraca bieżącą wartość x. Jest to trochę jak „zadzwoń po imieniu” używane w odległej przeszłości w językach.Przekazywanie 3 opakowań w celu uzyskania dostępu do zmiennej jest nieco niewygodne, więc można je zawinąć w klasę, która ma atrybut proxy:
Obsługa „refleksji” Pythona umożliwia uzyskanie obiektu, który jest w stanie ponownie przypisać nazwę / zmienną w danym zakresie bez wyraźnego zdefiniowania funkcji w tym zakresie:
Tutaj
ByRef
klasa otacza dostęp do słownika. Tak więc dostęp do atrybutuwrapped
jest tłumaczony na dostęp do elementu w przekazywanym słowniku. Po przekazaniu wyniku wbudowanejlocals
i nazwy zmiennej lokalnej uzyskuje się dostęp do zmiennej lokalnej. Dokumentacja Pythona od 3.5 radzi, że zmiana słownika może nie działać, ale wydaje mi się, że działa.źródło
biorąc pod uwagę sposób, w jaki Python obsługuje wartości i odniesienia do nich, jedynym sposobem na odwołanie się do atrybutu dowolnej instancji jest nazwa:
w prawdziwym kodzie dodawalibyśmy oczywiście sprawdzanie błędów podczas wyszukiwania słownika.
źródło
Ponieważ słowniki są przekazywane przez referencję, można użyć zmiennej dict do przechowywania w niej dowolnych wartości referencyjnych.
źródło
Przekazywanie przez referencję w Pythonie różni się znacznie od koncepcji przekazywania przez referencję w C ++ / Java.
źródło
Ponieważ twój przykład jest zorientowany obiektowo, możesz wprowadzić następującą zmianę, aby osiągnąć podobny wynik:
źródło
Możesz użyć pustej klasy jako instancji do przechowywania obiektów referencyjnych, ponieważ wewnętrzne atrybuty obiektów są przechowywane w słowniku instancji. Zobacz przykład.
źródło
Ponieważ wydaje się, że nigdzie nie wspomniano, podejście do symulacji referencji znanej np. Z C ++ polega na użyciu funkcji „aktualizacji” i przekazania jej zamiast faktycznej zmiennej (a raczej „nazwy”):
Jest to szczególnie przydatne w przypadku „odwołań tylko do wyjścia” lub w sytuacji, gdy istnieje wiele wątków / procesów (dzięki temu, że funkcja aktualizacji wątek / wieloprocesowość jest bezpieczna).
Oczywiście powyższe nie pozwala na odczyt wartości, a jedynie na jej aktualizację.
źródło