Python append () kontra operator + na listach, dlaczego dają różne wyniki?

113

Dlaczego te dwie operacje ( append()odpowiednio +) dają różne wyniki?

>>> c = [1, 2, 3]
>>> c
[1, 2, 3]
>>> c += c
>>> c
[1, 2, 3, 1, 2, 3]
>>> c = [1, 2, 3]
>>> c.append(c)
>>> c
[1, 2, 3, [...]]
>>> 

W tym ostatnim przypadku rekurencja jest nieskończona. c[-1]i csą takie same. Dlaczego jest inaczej w przypadku +operacji?

ooboo
źródło
1
z całym szacunkiem dla nowego, sensownego pytania: wróciłem do pierwotnego pytania, aby było jasne (1 pytanie na wątek, patrz SO FAQ). Poproś o nowe lub zadaj dodatkowe pytania w wątkach komentarzy pod każdą odpowiedzią. Uwaga: Twoje zmiany nie zostaną utracone, kliknij historię i możesz skopiować / wkleić ją do nowego pytania.
Abel
Podobne dla +=: stackoverflow.com/questions/725782/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
wydaje się, że daje różne odpowiedzi, ale nie tak. Jeśli chcesz dodać wartość za pomocą operatora +, użyj znaku []. c + = [c] da taki sam wynik jak append.
Sharif Chowdhury
@SharifChowdhury Wierzę, że uzyskasz ten sam wynik
trustory

Odpowiedzi:

142

Aby wyjaśnić „dlaczego”:

+Operacja dodaje tablicy elementy do oryginalnej tablicy. array.appendDziałanie wprowadza tablicę (lub dowolnego obiektu) do zakończenia początkowego tablicy, co daje w rezultacie w odniesieniu do siebie w tym miejscu (stąd nieskończonej rekurencji).

Różnica polega na tym, że operacja + działa specyficznie, gdy dodajesz tablicę (jest przeciążona jak inne, zobacz ten rozdział o sekwencjach) przez konkatenację elementu. Jednak metoda append robi dosłownie to, o co prosisz: dołącza obiekt po prawej stronie, który mu dajesz (tablicę lub inny obiekt), zamiast pobierać jego elementy.

Alternatywa

Użyj, extend()jeśli chcesz użyć funkcji, która działa podobnie do operatora + (jak pokazały tu również inne osoby). Nie jest mądrze robić coś odwrotnego: próbować naśladować dopisywanie za pomocą operatora + dla list (zobacz mój wcześniejszy link o tym, dlaczego).

Mała historia

Dla zabawy, trochę historii: narodziny modułu tablicy w Pythonie w lutym 1993 roku. Może cię to zaskoczyć, ale tablice zostały dodane długo po tym, jak powstały sekwencje i listy.

Abel
źródło
2
+1, ponieważ zawsze głosuję za dokładnymi informacjami. Linki do oficjalnych dokumentów to zawsze plus!
jathanizm
10
Kolejna część „dlaczego”: rozsądni ludzie oczekują +symetrii: łączenie listy z listą.
Beni Cherniavsky-Paskin
1
+1, Dobra uwaga, Beni (chociaż mógłbym uważać za „rozsądne” stwierdzenie, że „obiekt po prawej stronie jest dołączony do tablicy po lewej stronie”, ale osobiście uważam, że obecne zachowanie jest bardziej sensowne).
Abel
jeśli element jest pojedynczym łańcuchem, np. s = 'słowo', l = ['to', 'jest']. Wtedy l.append (s) i l + s powinny być takie same. Mam rację?
user3512680
23

Operator konkatenacji +jest binarnym operatorem wrostkowym, który po zastosowaniu do list zwraca nową listę zawierającą wszystkie elementy każdego z dwóch operandów. list.append()Metoda jest mutatorna listktórego dołącza swój jeden objectargument (w przykładzie konkretnego wykaz c) do przedmiotu list. W twoim przykładzie skutkuje to cdołączeniem odwołania do samego siebie (stąd nieskończona rekurencja).

Alternatywa dla konkatenacji „+”

list.extend()Sposób jest również sposób mutator który skleja jej sequenceargumentu z przedmiotem list. W szczególności dołącza każdy z elementów sequencew kolejności iteracji.

Na bok

Będąc operatorem, +zwraca wynik wyrażenia jako nową wartość. Będąc mutatormetodą nie łączącą , list.extend()modyfikuje listę tematów w miejscu i nic nie zwraca.

Tablice

Dodałem to ze względu na potencjalne zamieszanie, jakie może spowodować powyższa odpowiedź Abla, mieszając dyskusję na temat list, sekwencji i tablic. Arrayszostały dodane do Pythona po sekwencjach i listach, jako bardziej efektywny sposób przechowywania tablic integralnych typów danych. Nie myl arraysz lists. One nie są takie same.

Z dokumentacji tablicy :

Tablice są typami sekwencji i zachowują się bardzo podobnie do list, z wyjątkiem tego, że typ przechowywanych w nich obiektów jest ograniczony. Typ jest określany w czasie tworzenia obiektu przy użyciu kodu typu, który jest pojedynczym znakiem.

Dave
źródło
18

appenddołącza element do listy. jeśli chcesz rozszerzyć listę o nową listę, której musisz użyć extend.

>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]
SilentGhost
źródło
4
Pomyślałem, że jest całkiem jasne, dlaczego wyniki są różne, ponieważ operacje nie są takie same! gdyby tak się wydawało +i extendprzyniosło inne rezultaty, o których moglibyśmy pomyśleć.
SilentGhost
1
+1: Dlaczego nie lubię pytań „dlaczego”: appendi +są różne. Dlatego. Podoba mi się ta odpowiedź, ponieważ oferuje coś, co ma większy sens.
S.Lott,
Czy ta strona nie służy odpowiadaniu na zadawane pytania? Ludzie pytają, dlaczego PHP nazywa się PHP i dlaczego __lt__nie można go przeciążać w Pythonie (obecnie jest to możliwe). Pytania „dlaczego” są najbardziej istotne, ale często najtrudniejsze do udzielenia odpowiedzi: proszą o esencję, a nie o wskazówkę do instrukcji. I oczywiście: jeśli nie podoba ci się pytanie (nie lubię najbardziej), to nie odpowiadaj ;-)
Abel
Do dalszej demonstracji, może pokazu c += [c]i c.append(c[:])też.
ephemient
2
@Abel: Dlaczego a+b != a*b? To różne operacje. To jest odpowiedź. „Dlaczego” nie jest tak pomocne, jak inne pytania, na przykład „Jak prawidłowo dołączyć?” Lub „Co jest nie tak z tym dodatkiem, który prowadzi do nieskończonej rekurencji?” Pytania w formularzu „Co mam zrobić z X” lub „Co poszło nie tak, gdy zrobiłem X”? Lub „Co powinienem zrobić zamiast X” również pomoże komuś w nauce, ale dostarczy ukierunkowanych, użytecznych i wykonalnych odpowiedzi.
S.Lott,
8

Listy Pythona są niejednorodne, to znaczy elementy na tej samej liście mogą być obiektami dowolnego typu. Wyrażenie: c.append(c)dołącza obiekt cdo listy, co kiedykolwiek może być. W przypadku, gdy sama lista staje się członkiem listy.

Wyrażenie c += cdodaje dwie listy razem i przypisuje wynik do zmiennej c. Przeciążony +operator jest definiowany na listach, aby utworzyć nową listę, której zawartością są elementy z pierwszej listy i elementy z drugiej listy.

Są to więc tak naprawdę różne wyrażenia używane do robienia różnych rzeczy zgodnie z projektem.

Tendayi Mawushe
źródło
7

Metoda, której szukasz, to extend(). Z dokumentacji Pythona :

list.append(x)
    Add an item to the end of the list; equivalent to a[len(a):] = [x].

list.extend(L)
    Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.

list.insert(i, x)
    Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).
Chinmay Kanchi
źródło
3

powinieneś użyć rozszerzenia ()

>>> c=[1,2,3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]

inne informacje: dołącz vs. rozszerz

ghostdog74
źródło
2

Zobacz dokumentację :

list.append (x)

  • Dodaj pozycję na końcu listy; odpowiednik a [len (a):] = [x].

list.extend (L) - Rozszerza listę, dołączając wszystkie elementy na podanej liście; odpowiednik a [len (a):] = L.

c.append(c)„dołącza” c do siebie jako element . Ponieważ lista jest typem referencyjnym, tworzy to rekurencyjną strukturę danych.

c += cjest odpowiednikiem extend(c), który dołącza elementy c do c.

oefe
źródło