Qual é a diferença entre os métodos de lista do Python anexados e estendidos?

3116

Qual é a diferença entre os métodos de lista append()e extend()?

Claudiu
fonte

Respostas:

5255

append: Acrescenta um objeto no final.

x = [1, 2, 3]
x.append([4, 5])
print (x)

da-te: [1, 2, 3, [4, 5]]


extend: Estende a lista acrescentando elementos do iterável.

x = [1, 2, 3]
x.extend([4, 5])
print (x)

da-te: [1, 2, 3, 4, 5]

kender
fonte
122
Qual é a diferença entre extende simplesmente usar o operador de adição - no exemplo acima x = x + [4, 5]?
Rohan
303
Na verdade, há uma grande diferença - x + [4, 5]fornece uma nova lista atribuída a x - x.extend()altera a lista original. Eu elaboro na minha resposta aqui abaixo.
Aaron Hall
@AaronHall @Rohan, mas é o mesmo que x += [4,5].
Astitva Srivastava
1
@AstitvaSrivastava Na verdade, eu acho que se estendem é mais rápido em termos de bytecode
MilkyWay90
1
A palavra-chave ao usar appendé Object . Se você tentar usar extende passar um dicionário , ele acrescentará a chave e não o hash inteiro ao final da matriz.
Anthony
640

appendadiciona um elemento a uma lista e extendconcatena a primeira lista com outra lista (ou outra iterável, não necessariamente uma lista).

>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']

>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']

>>> li.append(["new", 2])
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2], 'two', 'elements']
Harley Holcombe
fonte
490

Qual é a diferença entre os métodos de lista anexados e estendidos?

  • appendadiciona seu argumento como um único elemento ao final de uma lista. O comprimento da lista em si aumentará em um.
  • extenditera sobre seu argumento, adicionando cada elemento à lista, estendendo a lista. O comprimento da lista aumentará no entanto, muitos elementos estavam no argumento iterável.

append

O list.appendmétodo anexa um objeto ao final da lista.

my_list.append(object) 

Qualquer que seja o objeto, seja um número, uma string, outra lista ou qualquer outra coisa, ele é adicionado ao final my_listcomo uma única entrada na lista.

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']

Portanto, lembre-se de que uma lista é um objeto. Se você anexar outra lista a uma lista, a primeira lista será um único objeto no final da lista (que pode não ser o que você deseja):

>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
                     #^^^^^^^^^--- single item at the end of the list.

extend

O list.extendmétodo estende uma lista anexando elementos de um iterável:

my_list.extend(iterable)

Portanto, com a extensão, cada elemento do iterável é anexado à lista. Por exemplo:

>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]

Lembre-se de que uma sequência é iterável; portanto, se você estender uma lista com uma sequência, anexará cada caractere à medida que itera sobre a sequência (que pode não ser o que você deseja):

>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']

Sobrecarga do operador, __add__( +) e __iadd__( +=)

Os operadores +e +=são definidos para list. Eles são semanticamente semelhantes para estender.

my_list + another_list cria uma terceira lista na memória, para que você possa retornar o resultado, mas requer que a segunda iterável seja uma lista.

my_list += another_listmodifica a lista no local ( é o operador no local e as listas são objetos mutáveis, como vimos), para que não crie uma nova lista. Também funciona como estender, pois o segundo iterável pode ser qualquer tipo de iterável.

Não se confunda - my_list = my_list + another_listnão é equivalente a +=- ela fornece uma nova lista atribuída a my_list.

Complexidade temporal

O anexo tem complexidade de tempo constante , O (1).

Estender possui complexidade de tempo, O (k).

A repetição de várias chamadas para appendaumentar a complexidade, tornando-a equivalente à extensão, e como a iteração da extensão é implementada em C, sempre será mais rápido se você desejar acrescentar itens sucessivos de uma iterável a uma lista.

atuação

Você pode se perguntar o que é de melhor desempenho, já que o anexo pode ser usado para obter o mesmo resultado que o prolongamento. As seguintes funções fazem a mesma coisa:

def append(alist, iterable):
    for item in iterable:
        alist.append(item)

def extend(alist, iterable):
    alist.extend(iterable)

Então vamos cronometrá-los:

import timeit

>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883

Endereçando um comentário sobre horários

Um comentarista disse:

Resposta perfeita, só sinto falta do tempo de comparar adicionando apenas um elemento

Faça a coisa semanticamente correta. Se você deseja anexar todos os elementos em um iterável, use extend. Se você está apenas adicionando um elemento, use append.

Ok, então vamos criar um experimento para ver como isso funciona com o tempo:

def append_one(a_list, element):
    a_list.append(element)

def extend_one(a_list, element):
    """creating a new list is semantically the most direct
    way to create an iterable to give to extend"""
    a_list.extend([element])

import timeit

E vemos que sair do nosso caminho para criar uma iterável apenas para usar a extensão é uma (menor) perda de tempo:

>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295

Aprendemos com isso que não se ganha nada usando extendquando temos apenas um elemento a acrescentar.

Além disso, esses horários não são tão importantes. Estou apenas mostrando a eles que, em Python, fazer a coisa semanticamente correta é fazer as coisas da maneira certa ™.

É concebível que você possa testar os tempos em duas operações comparáveis ​​e obter um resultado ambíguo ou inverso. Apenas se concentre em fazer a coisa semanticamente correta.

Conclusão

Vemos que extendé semanticamente mais clara, e que ele pode correr muito mais rápido do que append, quando você pretende anexar cada elemento em uma iterable a uma lista.

Se você tiver apenas um único elemento (não em um iterável) para adicionar à lista, use append.

Aaron Hall
fonte
1
@ Aaron Hall Um pequeno comentário no algoritmo de tempo. "extend_one" pode retornar um tempo "levemente errado" porque a criação de uma lista também está envolvida. Provavelmente o melhor é criar os itens como variáveis ​​( ex1 = 0e ex2 = [0]) e passar essas variáveis, se você quiser ser mais rigoroso.
Ilias Iliadis
19
Resposta perfeita de fato. E quanto ao desempenho de l1 += l2vs l1.extend(l2)?
Jean-François T.
6
@ Jean-FrancoisT .: l1 += l2e, l1.extend(l2)finalmente, executa o mesmo código (a list_extendfunção in listobject.c). As únicas diferenças são: 1. +=reatribuições l1(a si própria para lists, mas a reatribuição suporta tipos imutáveis ​​que não são o mesmo objeto depois), o que a torna ilegal se l1for realmente um atributo de um objeto imutável; por exemplo, t = ([],), t[0] += lstseria um fracasso, enquanto que t[0].extend(lst)iria funcionar. 2. l1 += l2usa bytecodes dedicados, enquanto l1.extend(l2)usa despacho de método generalizado; isso faz +=mais rápido que extend.
ShadowRanger
3
O fato de que +=deve ser reatribuído l1significa que, em alguns casos, a expedição mais lenta de extendé parcial ou totalmente compensada por não atribuir de volta ao lado esquerdo. Por exemplo, se listé o atributo de um objeto self.l1 += l2e self.l1.extend(l2)tem desempenho idêntico na minha instalação do Python 3.6, simplesmente porque a operação real é mais parecida self.l1 = self.l1.__iadd__(l2), o que significa que ela deve executar um custo moderadamente caro STORE_ATTRque self.l1.extend(l2)não precisa.
ShadowRanger
2
Comparação simples em testes locais: para uma variável local (portanto, +=está apenas usando STORE_FAST, o que é super barato), em que o valor adicionado é um existente listcom um item, com a operação repetida 1000 vezes, +=levou em média 33 ns , enquanto extendlevou 78 ns, uma diferença de 45 ns. Se l1for global (requer mais caro STORE_GLOBAL), a diferença diminui para 17 ns. Se l1for realmente local.l1(requer ainda mais caro STORE_ATTR), não há diferença significativa entre +=e extend(tempos aproximadamente idênticos; extendàs vezes vence).
ShadowRanger
121

appendacrescenta um único elemento. extendanexa uma lista de elementos.

Observe que se você passar uma lista para anexar, ela ainda adicionará um elemento:

>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
Greg Hewgill
fonte
62

Anexar vs Estender

insira a descrição da imagem aqui

Com anexar, você pode anexar um único elemento que estenderá a lista:

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

Se você deseja estender mais de um elemento, deve usar o extend, porque você pode anexar apenas um elemento ou uma lista de elementos:

>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]

Para que você obtenha uma lista aninhada

Em vez de estender, você pode estender um único elemento como este

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

Ou, diferentemente, do anexo, estenda mais elementos de uma vez, sem aninhar a lista na original (essa é a razão do nome estender)

>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]

Adicionando um elemento com os dois métodos

insira a descrição da imagem aqui

Anexar e estender podem adicionar um elemento ao final da lista, embora o acréscimo seja mais simples.

acrescentar 1 elemento

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

estender um elemento

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

Adicionando mais elementos ... com resultados diferentes

Se você usar o acréscimo para mais de um elemento, precisará passar uma lista de elementos como argumentos e obterá uma lista NESTED!

>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]

Com estender, você passa uma lista como argumento, mas obterá uma lista com o novo elemento que não está aninhado no antigo.

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

Portanto, com mais elementos, você usará o extend para obter uma lista com mais itens. No entanto, anexar uma lista não adicionará mais elementos à lista, mas um elemento que é uma lista aninhada, como você pode ver claramente na saída do código.

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Giovanni G. PY
fonte
61

Os dois trechos a seguir são semanticamente equivalentes:

for item in iterator:
    a_list.append(item)

e

a_list.extend(iterator)

O último pode ser mais rápido à medida que o loop é implementado em C.

Erik
fonte
20
Estendendo é ~ 4x mais rápido na minha máquina de anexação em um loop (16us vs 4us para 100 voltas de zeros)
Alex L
6
extend()provavelmente pré-aloca, enquanto append()provavelmente não.
Mad Physicist
@ MadPhysicist: Por uma questão de completude, haveria momentos em extend() que não é possível pré-alocar sensatamente, pois algumas iteráveis ​​não são implementadas __len__(), mas, como você, eu ficaria surpreso se não tentar. Parte do ganho de desempenho também advém da parte da iteração em C puro, em vez de em Python, como apontado na resposta de Aaron .
Soren Bjornstad 28/07/19
44

O append()método adiciona um único item ao final da lista.

x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']

O extend()método pega um argumento, uma lista e anexa cada um dos itens do argumento à lista original. (As listas são implementadas como classes. “Criar” uma lista é realmente instanciar uma classe. Como tal, uma lista possui métodos que operam nela.)

x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']

De mergulhar em Python .

CodyChan
fonte
Você não pode estender com apenas 6, pois não é iterável. E a segunda saída no seu exemplo está errada. 'abc' é adicionado como um único elemento desde que você o passou para extenduma lista com um elemento ['abc']: [1, 2, 3, 4, 5, 'abc']. Para fazer o seu exemplo de saída correta, altere a linha abc para: x.extend('abc'). E remova x.extend(6)ou mude para x.extend([6]).
aneroid 25/09
37

Você pode usar "+" para retornar a extensão, em vez de estender no lugar.

l1=range(10)

l1+[11]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

l2=range(10,1,-1)

l1+l2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]

Da mesma forma +=para o comportamento no local, mas com pequenas diferenças de append& extend. Uma das maiores diferenças de +=from appende extendé quando é usado em escopos de função, consulte esta postagem no blog .

denfromufa
fonte
O uso do '+' para retornar a extensão afeta a complexidade do tempo?
21415 franklin
5
@franklin, consulte esta resposta para mais detalhes: stackoverflow.com/a/28119966/2230844
denfromufa
1
Eu não vejo como isso responde à pergunta
pppery
22

append(object) - Atualiza a lista adicionando um objeto à lista.

x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]

extend(list) - Concatena essencialmente duas listas.

x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
[20, 21, 22, 23]
Chaitanya
fonte
20

extend()pode ser usado com um argumento iterador. Aqui está um exemplo. Você deseja fazer uma lista de uma lista de listas desta maneira:

De

list2d = [[1,2,3],[4,5,6], [7], [8,9]]

você quer

>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Você pode usar itertools.chain.from_iterable()para fazer isso. A saída deste método é um iterador. Sua implementação é equivalente a

def from_iterable(iterables):
    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
    for it in iterables:
        for element in it:
            yield element

De volta ao nosso exemplo, podemos fazer

import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))

e obtenha a lista de procurados.

Aqui está como equivalentemente extend()pode ser usado com um argumento iterador:

merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Kiriloff
fonte
2
Essa resposta não contrasta estender com acréscimo e, portanto, não responder à pergunta
pppery
19

É o equivalente appende o extenduso do +operador:

>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]
skdev75
fonte
Por que não = + ?! Mais conciso
denfromufa
16

append () : É basicamente usado no Python para adicionar um elemento.

Exemplo 1:

>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]

Exemplo 2:

>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]

estender () : onde estender (), é usado para mesclar duas listas ou inserir vários elementos em uma lista.

Exemplo 1:

>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]

Exemplo 2:

>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
O Gr8 Adakron
fonte
12

Um ponto interessante que foi sugerido, mas não explicado, é que o prolongamento é mais rápido do que o acréscimo. Para qualquer loop que tenha um acréscimo interno, deve ser considerado substituído por list.extend (elementos_processados).

Lembre-se de que a aprovação de novos elementos pode resultar na realocação de toda a lista para um local melhor na memória. Se isso for feito várias vezes porque anexamos 1 elemento por vez, o desempenho geral será prejudicado. Nesse sentido, list.extend é análogo a "" .join (stringlist).

bconstanzo
fonte
12

Anexar adiciona todos os dados de uma vez. Os dados completos serão adicionados ao índice recém-criado. Por outro lado,extend como o próprio nome sugere, estende a matriz atual.

Por exemplo

list1 = [123, 456, 678]
list2 = [111, 222]

Com appendnós obtemos:

result = [123, 456, 678, [111, 222]]

Enquanto extendestivermos em :

result = [123, 456, 678, 111, 222]
Shiv
fonte
8

Um dicionário de inglês define as palavras appende extendcomo:

acrescentar : adicione (algo) ao final de um documento escrito.
estender : aumentar. Ampliar ou expandir


Com esse conhecimento, agora vamos entender

1) A diferença entre appendeextend

append:

  • Anexa qualquer objeto Python como está no final da lista (ou seja, como o último elemento da lista).
  • A lista resultante pode ser aninhada e conter elementos heterogêneos (ou seja, lista, sequência, tupla, dicionário, conjunto, etc.)

extend:

  • Aceita qualquer iterable como seu argumento e faz parte da lista maior .
  • A lista resultante é sempre uma lista unidimensional (ou seja, sem aninhamento) e pode conter elementos heterogêneos (como caracteres, números inteiros, float) como resultado da aplicação list(iterable).

2) Semelhança entre appendeextend

  • Ambos aceitam exatamente um argumento.
  • Ambos modificam a lista no local .
  • Como resultado, os dois retornos None.

Exemplo

lis = [1, 2, 3]

# 'extend' is equivalent to this
lis = lis + list(iterable)

# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)
kmario23
fonte
5

Espero poder fazer um complemento útil para esta pergunta. Se sua lista armazena um objeto de tipo específico, por exemplo Info, aqui está uma situação em que o extendmétodo não é adequado: em um forloop ee gerando um Infoobjeto toda vez e usando-o extendpara armazená-lo em sua lista, ele falhará. A exceção é como abaixo:

TypeError: o objeto 'Info' não é iterável

Mas se você usar o appendmétodo, o resultado será OK. Como sempre, usando o extendmétodo, ele sempre será tratado como uma lista ou qualquer outro tipo de coleção, itere-o e coloque-o após a lista anterior. Um objeto específico não pode ser iterado, obviamente.

Crabime
fonte
4

Para distingui-los intuitivamente

l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]

É como l1reproduzir um corpo dentro do corpo (aninhado).

# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']

É como se dois indivíduos separados se casassem e construíssem uma família unida.

Além disso, faço uma cheatsheet exaustiva de todos os métodos da lista para sua referência.

list_methods = {'Add': {'extend', 'append', 'insert'},
                'Remove': {'pop', 'remove', 'clear'}
                'Sort': {'reverse', 'sort'},
                'Search': {'count', 'index'},
                'Copy': {'copy'},
                }
Cálculo
fonte
2

extend(L)estende a lista anexando todos os itens da lista fornecida L.

>>> a
[1, 2, 3]
a.extend([4])  #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
tessie
fonte
0

append"estende" a lista (no local) por apenas um item , o único objeto passado (como argumento).

extend"estende" a lista (no local) por tantos itens quanto o objeto passado (como argumento) contém.

Isso pode ser um pouco confuso para strobjetos.

  1. Se você passar uma string como argumento: appendadicionará um único item de string no final, mas extendadicionará tantos itens "str" ​​únicos quanto o comprimento dessa string.
  2. Se você passar uma lista de strings como argumento: appendainda adicionará um único item de 'lista' no final e extendadicionará tantos itens de 'lista' quanto o comprimento da lista passada.
def append_o(a_list, element):
    a_list.append(element)
    print('append:', end = ' ')
    for item in a_list:
        print(item, end = ',')
    print()

def extend_o(a_list, element):
    a_list.extend(element)
    print('extend:', end = ' ')
    for item in a_list:
        print(item, end = ',')
    print()
append_o(['ab'],'cd')

extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])

produz:

append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,
ilias iliadis
fonte
0

Anexar e estender são um dos mecanismos de extensibilidade em python.

Anexar: adiciona um elemento ao final da lista.

my_list = [1,2,3,4]

Para adicionar um novo elemento à lista, podemos usar o método append da seguinte maneira.

my_list.append(5)

O local padrão ao qual o novo elemento será adicionado está sempre na posição (comprimento + 1).

Inserção: O método de inserção foi usado para superar as limitações do anexo. Com a inserção, podemos definir explicitamente a posição exata em que queremos que nosso novo elemento seja inserido.

Descritor de método de inserção (índice, objeto). São necessários dois argumentos, primeiro sendo o índice que queremos inserir nosso elemento e depois o próprio elemento.

Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']

Estender: isso é muito útil quando queremos juntar duas ou mais listas em uma única lista. Sem extensão, se queremos juntar duas listas, o objeto resultante conterá uma lista de listas.

a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]

Se tentarmos acessar o elemento na posição 2, obteremos uma lista ([3]), em vez do elemento. Para juntar duas listas, teremos que usar append.

a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]

Para ingressar em várias listas

a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]
vivek
fonte
2
Por que você está respondendo a uma pergunta que já foi respondida várias vezes? Esta pergunta tem 10 anos ...
Mike - SMT