¿Cuál es la diferencia entre los métodos de lista de Python para agregar y extender?

Resuelto Claudiu asked hace 16 años • 20 respuestas

¿ Cuál es la diferencia entre los métodos de lista append()y extend()?

Claudiu avatar Oct 31 '08 12:10 Claudiu
Aceptado

.append()agrega un objeto específico al final de la lista:

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

.extend()extiende la lista agregando elementos del iterable especificado:

>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> print(x)
[1, 2, 3, 4, 5]
kender avatar Oct 31 '2008 06:10 kender

.append()agrega un elemento a una lista,
mientras que .extend()concatena la primera lista con otra lista/iterable.

>>> xs = ['A', 'B']
>>> xs
['A', 'B']

>>> xs.append("D")
>>> xs
['A', 'B', 'D']

>>> xs.append(["E", "F"])
>>> xs
['A', 'B', 'D', ['E', 'F']]

>>> xs.insert(2, "C")
>>> xs
['A', 'B', 'C', 'D', ['E', 'F']]

>>> xs.extend(["G", "H"])
>>> xs
['A', 'B', 'C', 'D', ['E', 'F'], 'G', 'H']
Harley Holcombe avatar Oct 31 '2008 05:10 Harley Holcombe

¿Cuál es la diferencia entre los métodos de lista agregar y extender?

  • .append()agrega su argumento como un solo elemento al final de una lista. La longitud de la lista aumentará en uno.
  • .extend()itera sobre su argumento agregando cada elemento a la lista, extendiendo la lista. La longitud de la lista aumentará según la cantidad de elementos que haya en el argumento iterable.

.append()

El .append()método agrega un objeto al final de la lista.

my_list.append(object) 

Cualquiera que sea el objeto, ya sea un número, una cadena, otra lista u otra cosa, se agrega al final my_listcomo una única entrada en la lista.

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

Tenga en cuenta que una lista es un objeto. Si agrega otra lista a una lista, la primera lista será un único objeto al final de la lista (que puede no ser lo que desea):

>>> 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()

El .extend()método extiende una lista agregando elementos de un iterable:

my_list.extend(iterable)

Entonces, con extender, cada elemento del iterable se agrega a la lista. Por ejemplo:

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

Tenga en cuenta que una cadena es iterable, por lo que si extiende una lista con una cadena, agregará cada carácter a medida que itera sobre la cadena (que puede no ser lo que desea):

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

Sobrecarga del operador, __add__( +) y __iadd__( +=)

Ambos operadores +y +=están definidos para list. Son semánticamente similares a extender.

my_list + another_listcrea una tercera lista en la memoria, por lo que puede devolver el resultado de la misma, pero requiere que el segundo iterable sea una lista.

my_list += another_listmodifica la lista in situ (es el operador in situ y las listas son objetos mutables, como hemos visto) para que no cree una lista nueva. También funciona como extender, en el sentido de que el segundo iterable puede ser cualquier tipo de iterable.

No se confunda, my_list = my_list + another_listno es equivalente a +=: le proporciona una lista nueva asignada a my_list.

Complejidad del tiempo

Append tiene una complejidad de tiempo constante ( amortizada ) , O(1).

Extender tiene complejidad temporal, O (k).

Iterar a través de las múltiples llamadas a .append()aumenta la complejidad, lo que lo hace equivalente a extender, y dado que la iteración de extend se implementa en C, siempre será más rápido si tiene la intención de agregar elementos sucesivos de un iterable a una lista.

Con respecto a "amortizado" - de la lista de fuentes de implementación de objetos :

    /* This over-allocates proportional to the list size, making room
     * for additional growth.  The over-allocation is mild, but is
     * enough to give linear-time amortized behavior over a long
     * sequence of appends() in the presence of a poorly-performing
     * system realloc().

Esto significa que obtenemos los beneficios de una reasignación de memoria mayor de la necesaria por adelantado, pero podemos pagarla en la siguiente reasignación marginal con una aún mayor. El tiempo total para todos los anexos es lineal en O (n), y el tiempo asignado por anexo se convierte en O (1).

Actuación

Quizás se pregunte qué es más eficaz, ya que append se puede utilizar para lograr el mismo resultado que extender. Las siguientes funciones hacen lo mismo:

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

Así que cronometrémoslos:

import timeit

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

Abordar un comentario sobre horarios

Un comentarista dijo:

Respuesta perfecta, solo extraño el momento de comparar agregando solo un elemento

Haz lo semánticamente correcto. Si desea agregar todos los elementos en un iterable, use .extend(). Si solo estás agregando un elemento, usa .append().

Bien, entonces creemos un experimento para ver cómo funciona esto con el tiempo:

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

Y vemos que hacer todo lo posible para crear un iterable solo para usar extender es una (menor) pérdida de tiempo:

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

De esto aprendemos que no se gana nada al usar .extend()cuando solo tenemos un elemento para agregar.

Además, estos tiempos no son tan importantes. Solo los muestro para dejar claro que, en Python, hacer lo semánticamente correcto es hacer las cosas de la manera correcta ™.

Es posible que pueda probar tiempos en dos operaciones comparables y obtener un resultado ambiguo o inverso. Solo concéntrate en hacer lo semánticamente correcto.

Conclusión

Vemos que .extend()es semánticamente más claro y que puede ejecutarse mucho más rápido que .append()cuando pretendes agregar cada elemento en un iterable a una lista.

Si solo tiene un elemento (no en un iterable) para agregar a la lista, use .append().

Russia Must Remove Putin avatar Jan 23 '2015 22:01 Russia Must Remove Putin

appendañade un solo elemento. extendañade una lista de elementos.

Tenga en cuenta que si pasa una lista para agregar, aún agrega un elemento:

>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
Greg Hewgill avatar Oct 31 '2008 05:10 Greg Hewgill