Eu vi que existem duas maneiras (talvez mais) de concatenar listas no Python: Uma maneira é usar o método extend ():
a = [1, 2]
b = [2, 3]
b.extend(a)
o outro para usar o operador mais (+):
b += a
Agora, eu me pergunto: Qual dessas duas opções é a maneira 'pitônica' de concatenação de listas e existe uma diferença entre as duas (procurei o tutorial oficial do Python, mas não consegui encontrar nada sobre esse tópico).
.__iadd__()
/.__add__()
/.__radd__()
contra.extend()
Respostas:
A única diferença no nível de bytecode é que o
.extend
caminho envolve uma chamada de função, que é um pouco mais cara no Python do que noINPLACE_ADD
.Você realmente não deve se preocupar com nada, a menos que esteja executando esta operação bilhões de vezes. É provável, no entanto, que o gargalo esteja em outro lugar.
fonte
.__iadd__()
/.__add__()
/.__radd__()
contra.extend()
Você não pode usar + = para variável não local (variável que não é local para a função e também não é global)
É porque, para o caso de extensão , o compilador carregará a variável
l
usando aLOAD_DEREF
instrução, mas para + = ele usaráLOAD_FAST
- e você obtém*UnboundLocalError: local variable 'l' referenced before assignment*
fonte
Você pode encadear chamadas de função, mas não pode + = uma chamada de função diretamente:
fonte
Eu diria que há alguma diferença quando se trata de numpy (acabei de ver que a pergunta é sobre concatenar duas listas, não numpy array, mas como pode ser um problema para iniciantes, como eu, espero que isso ajude alguém que buscam a solução para este post), por ex.
retornará com erro
ValueError: os operandos não puderam ser transmitidos junto com as formas (0,) (4,4,4)
b.extend(a)
funciona perfeitamentefonte
Do código fonte do CPython 3.5.2 : Não há grande diferença.
fonte
extend () funciona com qualquer iterável *, + = funciona com alguns, mas pode ficar estranho.
Python 3.6
* com certeza .extend () funciona com qualquer iterável, mas comente se estiver incorreto
fonte
list.extend(iterable) Extend the list by appending all the items from the iterable. Equivalent to a[len(a):] = iterable.
Acho que respondi meu próprio asterisco.+=
operador com objetos de tipos diferentes (ao contrário de duas listas, como na pergunta), não pode esperar que obtenha uma concatenação dos objetos. E você não pode esperar que haja umlist
tipo retornado. Dê uma olhada no seu código, você recebe um emnumpy.ndarray
vez delist
.Na verdade, existem diferenças entre as três opções:
ADD
,INPLACE_ADD
eextend
. O primeiro é sempre mais lento, enquanto os outros dois são aproximadamente os mesmos.Com essas informações, prefiro usar o
extend
que é mais rápido do queADD
e me parece mais explícito do que você está fazendoINPLACE_ADD
.Tente o seguinte código algumas vezes (para Python 3):
fonte
ADD
comINPLACE_ADD
eextend()
.ADD
produz uma nova lista e copia os elementos das duas listas originais. Com certeza será mais lento que a operação local deINPLACE_ADD
eextend()
.Esta informação está oculta nas Perguntas frequentes sobre programação :
Você também pode ver isso no código fonte do CPython: https://github.com/python/cpython/blob/v3.8.2/Objects/listobject.c#L1000-L1011
fonte
De acordo com o Python para análise de dados.
“Observe que a concatenação da lista por adição é uma operação relativamente cara, pois uma nova lista deve ser criada e os objetos copiados. Geralmente, é preferível usar o estender para anexar elementos a uma lista existente, especialmente se você estiver criando uma lista grande. " Portanto,
é mais rápido que a alternativa concatenativa:
fonte
everything = everything + temp
não é necessariamente implementado da mesma maneira queeverything += temp
.everything += temp
é implementado de uma maneira queeverything
não precisa ser copiada. Isso praticamente faz da sua resposta um ponto discutível.