Python: kiedy zmienna jest przekazywana przez referencję, a kiedy przez wartość? [duplikat]

Możliwy duplikat:
Python: jak przekazać zmienną przez odniesienie?

Mój kod:

locs = [ [1], [2] ]
for loc in locs:
    loc = []

print locs
# prints => [ [1], [2] ]

Dlaczego loc nie odnosi się do elementów locs?

Python: wszystko jest przekazywane jako odniesienie, chyba że jest wyraźnie skopiowane [czy to nie prawda ? ]

Proszę wyjaśnić.. w jaki sposób python decyduje o odwołaniu się i kopiowaniu ?

Update:

Jak to zrobić ?
def compute(ob):
   if isinstance(ob,list): return process_list(ob)
   if isinstance(ob,dict): return process_dict(ob)

for loc in locs:
   loc = compute(loc)  # What to change here to make loc a reference of actual locs iteration ?
  • locs musi zawierać ostateczną przetworzoną odpowiedź !
  • nie chcę używać enumerate, czy jest to możliwe bez niego ?
Author: Community, 2012-03-14

6 answers

Wszystko w Pythonie jest przekazywane i przypisywane przez wartość, tak samo jak wszystko jest przekazywane i przypisywane przez wartość w Javie. Każda wartość w Pythonie jest odniesieniem (wskaźnikiem) do obiektu. Obiekty nie mogą być wartościami. Assignment zawsze kopiuje wartość (która jest wskaźnikiem); dwa takie wskaźniki mogą zatem wskazywać na ten sam obiekt. Obiekty nigdy nie są kopiowane, chyba że robisz coś jawnego, aby je skopiować.

W Twoim przypadku każda iteracja pętli przypisuje element listy do zmienna loc. Następnie przypisujesz coś innego do zmiennej loc. Wszystkie te wartości są wskaźnikami; przypisujesz wskaźniki; ale nie wpływasz w żaden sposób na żadne obiekty.

 21
Author: newacct,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 19:39:15

Effbot (znany jako Fredrik Lundh) opisał zmienny styl przekazywania Pythona jako wywołanie przez obiekt: http://effbot.org/zone/call-by-object.htm

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

  • kiedy wykonujesz przypisanie, takie jak x = 1000, tworzony jest wpis słownikowy, który mapuje łańcuch " x " w bieżącej przestrzeni nazw na wskaźnik do obiektu integer zawierającego tysiąc.
  • po aktualizacji "x" z x = 2000, tworzony jest nowy obiekt integer i słownik jest aktualizowany tak, aby wskazywał na nowy obiekt. Stary obiekt tysiąc jest niezmieniony (i może, ale nie musi być żywy, w zależności od tego, czy cokolwiek innego odnosi się do obiektu).
  • kiedy wykonujesz nowe przypisanie, takie jak y = x, tworzony jest nowy wpis słownikowy "y", który wskazuje na 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 może zmieniać obiekt po jego wytworzeniu. Na przykład, po utworzeniu obiektu integer one-thousand, nigdy się nie zmieni. Matematyka jest wykonywana przez tworzenie nowych obiektów całkowitych.
  • obiekty takie jak listy są mutowalne . Oznacza to, że zawartość obiektu może być zmieniana przez cokolwiek wskazującego 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) listę obiekt (jak dodanie rekordu do bazy danych) i 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.

 45
Author: Raymond Hettinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-02 20:59:26

W Pythonie nie pomaga myślenie w kategoriach odniesień lub wartości. Ani nie jest poprawne.

W Pythonie zmienne są tylko nazwami. W pętli for, {[1] } jest tylko nazwą wskazującą na bieżący element na liście. Wykonując loc = [] po prostu rebinduje nazwę loc do innej listy, pozostawiając tylko oryginalną wersję.

Ale ponieważ w twoim przykładzie każdy element jest listą, możesz w rzeczywistości zmutować Ten element, a to będzie odzwierciedlone w oryginale lista:

for loc in locs:
    loc[0] = loc[0] * 2
 8
Author: Daniel Roseman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 05:42:13

Kiedy mówisz

loc = []

Zmieniasz zmienną loc na nowo utworzoną pustą listę

Być może chcesz

loc[:] = []

Który przypisuje wycinek (który jest całą listą) loc do pustej listy

 4
Author: John La Rooy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 05:40:29

Wszystko jest przekazywane przez obiekt. Rebinding i mutacja to różne operacje.

locs = [ [1], [2] ]
for loc in locs:
    del loc[:]

print locs
 2
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 05:39:45

Dlaczego loc nie jest odniesieniem do elementów locs ?

Jest . A przynajmniej jest w tym samym sensie, co każda inna zmienna w Pythonie. Zmienne Pythona są nazwami , a nie storage . {[1] } jest nazwą, która odnosi się do elementów [[1,2], [3,4]], podczas gdy {[3] } jest nazwą, która odnosi się do całej struktury.

loc = []

To nie oznacza "spójrz na to, co loc nazywa i powoduje, że zmienia się w []". It cannot oznacza to, że obiekty Pythona nie są zdolne do tego typu rzeczy.

Zamiast tego oznacza " ponieważ loc przestaje być nazwą dla rzeczy, dla której jest obecnie nazwą, i zaczyna być nazwą dla []". (Oczywiście, oznacza to konkretny [], który jest tam dostarczany, ponieważ ogólnie może być kilka obiektów w pamięci, które są takie same.)

Oczywiście zawartość locs nie ulega zmianie.

 2
Author: Karl Knechtel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 07:14:34