Ir al contenido
wannacode

Listas: append, remove y sort

En resumen: Una lista es una colección que crece y se encoge: append añade al final, remove saca un elemento sin dejar huecos, y sort la pone en orden.

Problema

El carrito está lleno

Estás escribiendo el carrito de compras de una tienda en línea, y guardas los productos en una lista, como en la lección sobre arrays: cada producto en su propio índice. Pero no puedes escribir más allá del final: cart[3] = "Mantequilla" detiene el programa con IndexError: list assignment index out of range. Así que para un cuarto producto creas una lista nueva, más larga. Y cuando el cliente quita un producto, queda un hueco:

cart = ["Pan", "Leche", "Café"]
# Un cuarto producto: cart[3] = "Mantequilla" se detiene con IndexError,
# así que creamos una lista nueva, más larga.
cart = cart + ["Mantequilla"]
# El cliente quita la leche.
cart[1] = None
for item in cart:
print(item)
Salida
Pan
None
Café
Mantequilla
Ahora cada bucle sobre el carrito tiene que saltarse None. Y el número de productos ya no es len(cart).

Es mucho código para algo que toda tienda hace todo el tiempo.

La idea

append y remove: la lista se cuida sola

La lista tiene métodos que hacen esto por ti. Por dentro sigue guardando los elementos en un array, pero copia y desplaza sola. Una colección que crece y se encoge así se llama lista:

cart = []
cart.append("Pan")
cart.append("Leche")
cart.append("Café")
cart.append("Mantequilla")
cart.remove("Leche")
print(cart)
print("Productos:", len(cart))
Salida
['Pan', 'Café', 'Mantequilla']
Productos: 3
  • append añade al final.
  • remove quita el elemento con ese valor y cierra el hueco: «Café» pasa al lugar de «Leche». Si el valor está varias veces, quita el primero.
  • len(cart) es cuántos elementos hay ahora mismo.
  • print imprime toda la lista entre corchetes, con el texto entre comillas.

Esto es lo que hace la lista por dentro. Tú no eliges cuántos lugares tiene el array. Lo decide CPython, el programa que ejecuta tu código. Una lista de 4 productos escrita en el código tiene exactamente 4 lugares, así que el array se llena con el quinto:

cart = ["Pan", "Leche", "Café", "Mantequilla"]
cart.append("Queso")
cart.remove("Leche")
print(cart)
print("Productos:", len(cart))
Paso a paso, en palabras
  1. cart apunta a un objeto list. Dentro hay un contador ob_size y un array ob_item con 4 lugares.
  2. Los productos del código llenan los lugares uno a uno. El array está lleno: 4 de 4.
  3. No hay sitio. append reserva un array con 8 lugares, y los elementos pasan a él.
  4. Ahora ob_item apunta al array nuevo. «Queso» va al primer lugar libre.
  5. remove quita «Leche», y todo lo que viene después se mueve un lugar a la izquierda. No queda ningún hueco.
  6. Desde fuera solo ves una lista de cuatro productos. CPython decide cuántos lugares tiene por dentro: el lenguaje no lo promete.

La idea

Qué va en una lista

Una lista no pregunta qué pones en ella. Un texto y un número pueden estar uno al lado del otro:

cart = []
cart.append("Pan")
cart.append(5)
print(cart)
Salida
['Pan', 5]

Parece práctico, pero el error aparece más tarde, donde esperas texto. Por ejemplo, un bucle que imprime los productos en mayúsculas:

cart = ["Pan", 5]
for item in cart:
print(item.upper())
Error
AttributeError: 'int' object has no attribute 'upper'

«Pan» se imprime, y el programa se detiene en el número. Por eso una lista guarda un solo tipo de cosa: solo productos, solo precios.

Eso lo puedes dejar escrito con una anotación de tipo (type hint): list[str] significa «una lista de texto».

cart: list[str] = []
cart.append("Pan")
cart.append(5)
print(cart)
Salida
['Pan', 5]

Python no comprueba la anotación mientras el programa se ejecuta: el número entra igual. Tu editor y herramientas como mypy la comprueban antes de que ejecutes el programa. Esta lección no tiene anotaciones, pero las verás en el código de otras personas.

La idea

Índices: [i], insert, index, in

Una lista tiene índices como un array, del 0 a len(tasks) - 1, y los escribes con los mismos [ ]:

tasks = ["Factura de marzo", "Llamar al banco", "Informe del almacén"]
print(tasks[0])
tasks[1] = "Reunión en el banco"
tasks.insert(0, "Café con el equipo")
print(tasks)
print(tasks.index("Informe del almacén"))
print("Llamar al banco" in tasks)
Salida
Factura de marzo
['Café con el equipo', 'Factura de marzo', 'Reunión en el banco', 'Informe del almacén']
3
False
  • tasks[i] lee, y tasks[i] = x reemplaza.
  • insert(i, x) inserta en el índice i y desplaza el resto a la derecha.
  • index(x) busca y devuelve el índice, y x in tasks solo dice si está.
Más precisamente, para curiosos
  • Un índice fuera de la lista detiene el programa. Un índice negativo cuenta desde atrás: tasks[-1] es la última tarea. Y index de algo que no está también detiene el programa, así que pregunta primero con in:
tasks = ["Factura de marzo", "Llamar al banco", "Informe del almacén"]
try:
print(tasks[3])
except IndexError as e:
print(f"IndexError: {e}")
print(tasks[-1])
try:
tasks.index("Nóminas")
except ValueError as e:
print(f"ValueError: {e}")
Salida
IndexError: list index out of range
Informe del almacén
ValueError: 'Nóminas' is not in list
  • in e index comparan con ==. Por eso encuentran un texto igual, no solo el mismo objeto.
  • Insertar y quitar al principio es lento en una lista grande: cada elemento después del índice se mueve un lugar. Con un millón de elementos, son un millón de movimientos.

Pruébalo

¿Quién sigue?

La lista de pacientes que esperan en el médico. Juan entra, y Ana tiene cita, así que ocupa el segundo lugar.

¿Qué imprimirá el programa?

waiting = ["Juan", "María", "Pedro"]
waiting.pop(0)
waiting.insert(1, "Ana")
print(waiting, len(waiting))
Respuesta

La idea

Recorrer los elementos

Recorres una lista con for cuando solo necesitas los elementos. Cuando también necesitas el número, está enumerate:

cart = ["Pan", "Café", "Mantequilla"]
for item in cart:
print(f"- {item}")
for number, item in enumerate(cart, start=1):
print(f"{number}. {item}")
Salida
- Pan
- Café
- Mantequilla
1. Pan
2. Café
3. Mantequilla

enumerate(cart, start=1) da dos valores en cada paso: el número y el elemento. Sin start=1, los números empiezan en 0, como los índices. También puedes usar un índice, como en la lección sobre arrays, con for i in range(len(cart)), pero enumerate es la forma habitual en Python.

Más precisamente, para curiosos
  • No quites elementos de una lista mientras la recorres con for. El programa no se detiene, pero se salta elementos:
cart = ["Pan", "Pan", "Leche"]
for item in cart:
if item == "Pan":
cart.remove(item)
print(cart)
Salida
['Pan', 'Leche']

El segundo «Pan» se quedó. remove desplazó todo a la izquierda, y el bucle siguió desde el índice siguiente y nunca lo vio. No hay error, así que un fallo así es difícil de detectar.

  • Si tienes que quitar, recorre con un índice de atrás hacia delante. Así, quitar no desplaza los elementos que todavía no has comprobado:
cart = ["Pan", "Pan", "Leche"]
for i in range(len(cart) - 1, -1, -1):
if cart[i] == "Pan":
cart.pop(i)
print(cart)
Salida
['Leche']
En el módulo «Python moderno» verás una forma más corta que crea una lista nueva solo con los elementos que quieres.

La idea

Números en una lista

Una lista de puntuaciones es como una lista de texto. El número está en la lista tal cual:

scores = [85, 64, 91]
total = 0
for score in scores:
total += score
print("Media:", total / len(scores))
print("Media:", sum(scores) / len(scores))
Salida
Media: 80.0
Media: 80.0
  • / da un número decimal, así que la media es 80.0, no 80.
  • sum suma todos los números de la lista. Las dos líneas calculan lo mismo.
Más precisamente, para curiosos
  • En Python, un número también es un objeto. Para los números pequeños, del -5 al 256, Python guarda objetos ya hechos, y para los más grandes crea objetos nuevos. Por eso is, que pregunta «¿es el mismo objeto?», da respuestas distintas:
a = int("256")
b = int("256")
c = int("257")
d = int("257")
print(a is b)
print(c is d)
print(c == d)
Salida
True
False
True

Compara números y texto con ==: pregunta si los valores son iguales. is es para None: if found is None.

Pruébalo

Encuentra el error

Un teatro guarda los asientos ocupados en una lista. Un cliente deja el asiento 2, y el programa debería imprimir [12, 7, 5]. En cambio imprime [12, 2, 5]. ¿Qué línea tiene el error?

Elige la línea con el error.

La idea

Ordenar y una lista que no cambia

sort() ordena la lista en el sitio: el texto en orden alfabético, los números por tamaño. sorted(...) no toca nada. Devuelve una lista nueva, ordenada.

cities = ["Sevilla", "Madrid", "Valencia"]
cities.sort()
print(cities)
prices = (30, 5, 12)
print(sorted(prices))
Salida
['Madrid', 'Sevilla', 'Valencia']
[5, 12, 30]

Los precios están entre paréntesis: (30, 5, 12). Es una tupla (tuple), una lista inmutable. Puedes leerla y recorrerla, pero no puedes añadir, quitar ni ordenar en ella:

days = ("lun", "mar", "mié")
days.append("jue")
Error
AttributeError: 'tuple' object has no attribute 'append'

Por eso los precios de arriba se ordenan con sorted: devuelve una lista nueva, y la tupla sigue igual. Una tupla es para cosas que no cambian: los días de la semana, las dos coordenadas de un punto.

Más precisamente, para curiosos
  • El texto se ordena por los códigos de sus caracteres. Las mayúsculas van antes que las minúsculas, así que «Pera» va antes que «manzana»:
fruit = ["manzana", "Pera", "banana", "Uva"]
fruit.sort()
print(fruit)
Salida
['Pera', 'Uva', 'banana', 'manzana']
  • Cómo ordenar tus propios objetos, por ejemplo productos por precio, lo verás en la lección «Clases anidadas».

Ejercicio

Listas en clases

Resuelve las tareas en tu editor. La lista es un campo de la clase con un _ delante («no tocar desde fuera»), y el código debajo de las clases solo llama a sus métodos.

1. Una estantería. Una clase BookShelf con un método add_book(title) que pone el libro al final, y take_book(), que devuelve y quita el primer libro (o None si la estantería está vacía). Añade count() y __str__(). Añade «Bajo el yugo», «Tabaco» y «El candelabro de hierro», toma un libro e imprime el resto.

Salida
Tomado: Bajo el yugo
2 quedan: ['Tabaco', 'El candelabro de hierro']

2. Un registro de eventos. Una clase Event con una fecha y una descripción, y una clase EventLog con los métodos add_event(date, description) y get_events_between(start, end), que devuelve una lista con los eventos entre las dos fechas, incluidas. Las fechas son texto con la forma 2026-03-31. Con esta forma, el texto se ordena igual que las fechas, así que <= y >= las comparan correctamente. Añade cuatro eventos: 2026-01-15 «Inventario anual», 2026-03-31 «Informe del primer trimestre», 2026-05-20 «Nuevo proveedor de café», 2026-09-01 «Nuevo curso escolar». Imprime los del 2026-03-01 al 2026-06-30.

Salida
2026-03-31 Informe del primer trimestre
2026-05-20 Nuevo proveedor de café

3. Un cuaderno. Una clase Note con un título y un contenido, y una clase Notebook con los métodos add_note, find_note(title) (devuelve la nota o None), delete_note(title) (devuelve True si borró algo) y count(). Añade las notas «POO», «Colecciones» y «SQL», busca «Colecciones», borra «POO» y comprueba que ya no está.

Salida
Colecciones: la lista crece sola
Borrada: POO
Notas: 2
No hay ninguna nota de POO.

4. Cálculo mental. Una clase Question con un texto y la respuesta correcta, y una clase MathGame con una lista de preguntas, un método add_question y un método start(). start hace las preguntas una a una, lee la respuesta y al final dice cuántas fueron correctas. Las preguntas son 2 + 2, 3 * 4 y 15 - 9.

Entrada
4
12
7
Salida
2 + 2 = ¡Correcto!
3 * 4 = ¡Correcto!
15 - 9 = Incorrecto, la respuesta es 6.
Puntuación: 2 de 3

Más tareas

  • Sin repetidos. Lee 6 nombres y reúnelos en una lista, saltándote los que ya están. Para la entrada Juan, María, Juan, Ana, María, Pedro la salida es ['Juan', 'María', 'Ana', 'Pedro'].
  • El producto más caro. Una lista guarda precios. Encuentra el más alto y su índice, sin max.
  • La lista al revés. Escribe una función que devuelva una lista nueva con los mismos elementos en orden inverso. No cambies el original.
  • Una lista de la compra. Lee las órdenes add milk, remove milk, list y end, y guarda la lista entre ellas. La orden de quitar un producto que no está dice «No existe ese producto.».

Test

Ponte a prueba

1. ¿Por qué append y remove son más prácticos que escribir por índice?
2. Hasta ahora cart solo tiene texto. ¿Qué hace cart.append(5)?
3. seats es [12, 2, 7, 5]. ¿Qué queda después de seats.pop(2)?
4. tasks tiene 3 tareas. ¿Qué hace print(tasks[3])?
5. days = ("lun", "mar"). ¿Qué pasa con days.append("mié")?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·