Operador append () vs. + do Python nas listas, por que eles fornecem resultados diferentes?

113

Por que essas duas operações ( append()resp. +) Fornecem resultados diferentes?

>>> 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, [...]]
>>> 

No último caso, há realmente uma recursão infinita. c[-1]e csão iguais. Por que é diferente com a +operação?

ooboo
fonte
1
com todo o devido respeito a uma nova pergunta viável: eu voltei para a pergunta original para mantê-la limpa (1 pergunta por tópico, consulte SO FAQ). Faça uma pergunta nova ou faça perguntas de acompanhamento dentro dos tópicos de comentários abaixo de cada resposta. Nota: suas edições não são perdidas, clique no histórico e você pode copiar / colar em uma nova pergunta.
Abel
Semelhante para +=: stackoverflow.com/questions/725782/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
parece que dá ans diferentes, mas não assim. Se você quiser adicionar um valor usando o operador +, você deve usar o sinal []. c + = [c] fornecerá o mesmo resultado que anexar.
Sharif Chowdhury
@SharifChowdhury, acredito que você obterá o mesmo resultado
confiável em

Respostas:

142

Para explicar o "porquê":

A +operação adiciona os elementos da matriz à matriz original. A array.appendoperação insere a matriz (ou qualquer objeto) no final da matriz original, o que resulta em uma referência a si mesmo naquele ponto (daí a recursão infinita).

A diferença aqui é que a operação + atua de maneira específica quando você adiciona um array (está sobrecarregado como os outros, consulte este capítulo sobre sequências) concatenando o elemento. O método append, entretanto, faz literalmente o que você pede: acrescenta o objeto no lado direito que você deu a ele (o array ou qualquer outro objeto), em vez de pegar seus elementos.

Uma alternativa

Use extend()se quiser usar uma função que atua de forma semelhante ao operador + (como outros também mostraram aqui). Não é aconselhável fazer o oposto: tentar imitar o acréscimo com o operador + para listas (veja meu link anterior sobre o porquê).

Pouca historia

Para se divertir, um pouco de história: o nascimento do módulo array em Python em fevereiro de 1993. pode surpreendê-lo, mas os arrays foram adicionados depois que as sequências e listas passaram a existir.

Abel
fonte
2
+1 porque sempre voto a favor de informações precisas. Links para documentos oficiais são sempre uma vantagem!
jathanism
10
Outra parte do "porquê": pessoas sãs esperam +ser simétricas: concatenar lista com lista.
Beni Cherniavsky-Paskin
1
+1, Bom ponto, Beni (embora eu pudesse considerar igualmente "lógico" dizer "o objeto do lado direito está anexado à matriz do lado esquerdo", mas pessoalmente acho o comportamento atual mais sensato).
Abel
se um elemento é uma string única, por exemplo, s = 'palavra', l = ['isto', 'é']. Então, l.append (s) e l + s devem ser iguais. Estou correcto?
user3512680
23

O operador de concatenação +é um operador de infixo binário que, quando aplicado a listas, retorna uma nova lista contendo todos os elementos de cada um de seus dois operandos. O list.append()método é um mutatorno listqual anexa seu único objectargumento (em seu exemplo específico, a lista c) ao assunto list. Em seu exemplo, isso resulta no cacréscimo de uma referência a si mesmo (daí a recursão infinita).

Uma alternativa para concatenação '+'

O list.extend()método também é um método modificador que concatena seu sequenceargumento com o assunto list. Especificamente, ele anexa cada um dos elementos de sequencena ordem de iteração.

Um aparte

Sendo um operador, +retorna o resultado da expressão como um novo valor. Por ser um mutatormétodo sem encadeamento , list.extend()modifica a lista de assuntos no local e não retorna nada.

Arrays

Eu adicionei isso devido à confusão potencial que a resposta de Abel acima pode causar ao misturar a discussão de listas, sequências e matrizes. Arraysforam adicionados ao Python após sequências e listas, como uma maneira mais eficiente de armazenar matrizes de tipos de dados integrais. Não confunda arrayscom lists. Eles não são os mesmos.

Dos documentos do array :

Arrays são tipos de sequência e se comportam de maneira muito semelhante a listas, exceto que o tipo de objetos armazenados neles é restrito. O tipo é especificado no momento da criação do objeto usando um código de tipo, que é um único caractere.

Dave
fonte
18

appendestá anexando um elemento a uma lista. se você quiser estender a lista com a nova lista que você precisa usar extend.

>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]
SilentGhost
fonte
4
Achei bem claro porque os resultados são diferentes, porque as operações não são as mesmas! se parecesse isso +e extendproduzisse resultados diferentes nos quais teríamos algo em que pensar.
SilentGhost
1
+1: Por que eu não gosto de perguntas "por que": appende +são diferentes. É por isso. Gosto dessa resposta porque oferece o que fazer que faz mais sentido.
S.Lott
Este site não é sobre como responder às perguntas feitas? As pessoas perguntam por que o PHP é chamado de PHP e por __lt__que não podia ser sobrecarregado no Python (hoje em dia pode). As perguntas por que são as mais essenciais, mas geralmente as mais difíceis de responder: elas pedem a essência, não uma indicação do manual. E claro: se você não gosta de uma pergunta (eu não gosto mais), então não responda ;-)
Abel
Para mais demonstração, talvez mostre c += [c]e c.append(c[:])também.
efêmero de
2
@Abel: Por quê a+b != a*b? Eles são operações diferentes. Essa é a resposta. "Por que" não é tão útil quanto outras perguntas, como "Como posso anexar corretamente?" Ou "O que há de errado com este apêndice que leva à recursão infinita?" Perguntas do tipo "O que faço com X" ou "O que deu errado quando fiz X"? Ou "O que devo fazer em vez de X" também ajudará alguém a aprender, mas fornecerá respostas focadas, utilizáveis ​​e acionáveis.
S.Lott
8

As listas do Python são heterogêneas, ou seja, os elementos da mesma lista podem ser qualquer tipo de objeto. A expressão: c.append(c)anexa o objeto c, seja ele qual for, à lista. No caso, torna a própria lista um membro da lista.

A expressão c += cadiciona duas listas e atribui o resultado à variável c. O +operador sobrecarregado é definido em listas para criar uma nova lista cujo conteúdo são os elementos da primeira lista e os elementos da segunda lista.

Portanto, essas são apenas expressões diferentes usadas para fazer coisas diferentes por design.

Tendayi Mawushe
fonte
7

O método que você está procurando é extend(). Da documentação do Python :

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
fonte
3

você deve usar extend ()

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

outras informações: anexar vs. estender

ghostdog74
fonte
2

Veja a documentação :

list.append (x)

  • Adicione um item ao final da lista; equivalente a [len (a):] = [x].

list.extend (L) - Estenda a lista anexando todos os itens na lista fornecida; equivalente a [len (a):] = L.

c.append(c)"anexa" c a si mesmo como um elemento . Como uma lista é um tipo de referência, isso cria uma estrutura de dados recursiva.

c += cé equivalente a extend(c), que anexa os elementos de c a c.

Oefe
fonte