Listas en Python
En esta lección
- Crear una lista
- Acceder a los elementos: índices
- Slicing: trozos de una lista
- Añadir elementos
- Quitar elementos
- Buscar: in, index y count
- Funciones útiles: len, sum, min, max
- Ordenar: sort frente a sorted
- Copiar listas: referencias frente a copias
- Listas anidadas
- Desempaquetado
- Recorrer una lista con enumerate
- Listas y textos
- Errores frecuentes
- Resumen
Una lista guarda varios valores en orden dentro de una sola variable. Es la colección más usada de Python y el equivalente a los arrays de otros lenguajes. En esta lección aprenderás a crear listas, leer y cambiar sus elementos, sacar trozos, añadir y quitar, ordenar, y un detalle que causa muchos errores: la diferencia entre copiar una lista y tener dos nombres para la misma.
Crear una lista
Los elementos van entre corchetes y separados por comas:
frutas = ["manzana", "pera", "kiwi"]
notas = [7, 9.5, 5, 8]
mezcla = ["Ana", 25, True] # puede mezclar tipos
vacia = []
letras = list("hola") # ['h', 'o', 'l', 'a']
numeros = list(range(1, 6)) # [1, 2, 3, 4, 5]
Aunque se pueden mezclar tipos, lo normal es que todos los elementos sean del mismo tipo: una lista de nombres, una lista de precios…
Las listas son ordenadas (mantienen el orden en que metes los elementos), admiten duplicados y son mutables: puedes cambiarlas después de crearlas, al contrario que las cadenas.
Acceder a los elementos: índices
Cada elemento tiene una posición que empieza en 0. Los índices negativos cuentan desde el final:
frutas = ["manzana", "pera", "kiwi", "uva"]
print(frutas[0]) # manzana
print(frutas[2]) # kiwi
print(frutas[-1]) # uva (el último)
print(frutas[-2]) # kiwi (el penúltimo)
print(len(frutas)) # 4
frutas[-1] es la forma habitual de obtener el último elemento sin saber cuántos hay.
Para cambiar un elemento, asígnale un valor nuevo:
frutas[1] = "mango"
print(frutas)
# ['manzana', 'mango', 'kiwi', 'uva']
Si pides una posición que no existe, obtienes IndexError: list index out of range. En una lista de 4 elementos, el último índice válido es 3.
Slicing: trozos de una lista
lista[inicio:fin:paso] devuelve una lista nueva con los elementos desde inicio hasta fin sin incluirlo:
numeros = [10, 20, 30, 40, 50, 60]
print(numeros[1:4]) # [20, 30, 40]
print(numeros[:3]) # [10, 20, 30] los tres primeros
print(numeros[3:]) # [40, 50, 60] desde el índice 3 al final
print(numeros[-2:]) # [50, 60] los dos últimos
print(numeros[::2]) # [10, 30, 50] uno sí, uno no
print(numeros[::-1]) # [60, 50, 40, 30, 20, 10] al revés
print(numeros[:]) # copia completa
Una forma de recordarlo: lista[:n] son los n primeros y lista[-n:] los n últimos. Y lista[:n] + lista[n:] siempre reconstruye la lista original.
El slicing no da error si los límites se salen: numeros[4:100] devuelve [50, 60].
También puedes asignar a un trozo para reemplazar varios elementos de golpe:
numeros = [10, 20, 30, 40, 50]
numeros[1:3] = [0, 0, 0]
print(numeros)
# [10, 0, 0, 0, 40, 50]
Añadir elementos
tareas = ["estudiar"]
tareas.append("comprar") # añade un elemento al final
tareas.insert(0, "desayunar") # inserta en una posición
tareas.extend(["entrenar", "leer"]) # añade todos los de otra lista
print(tareas)
# ['desayunar', 'estudiar', 'comprar', 'entrenar', 'leer']
Fíjate en la diferencia entre append y extend con una lista:
a = [1, 2]
a.append([3, 4])
print(a) # [1, 2, [3, 4]] mete la lista entera como un elemento
b = [1, 2]
b.extend([3, 4])
print(b) # [1, 2, 3, 4] mete cada elemento
También puedes unir listas con + (crea una nueva) y repetirlas con *: [0] * 5 da [0, 0, 0, 0, 0].
Quitar elementos
tareas = ["desayunar", "estudiar", "comprar", "entrenar"]
tareas.remove("comprar") # borra por valor (el primero que encuentre)
ultima = tareas.pop() # quita el último y lo devuelve
primera = tareas.pop(0) # quita el de la posición 0 y lo devuelve
print(ultima, primera) # entrenar desayunar
print(tareas) # ['estudiar']
del tareas[0] # borra por posición, sin devolver nada
tareas.clear() # vacía la lista
print(tareas) # []
| Método | Borra por | Devuelve el elemento | Si no existe |
|---|---|---|---|
remove(valor) | Valor | No | ValueError |
pop(indice) | Posición (por defecto, la última) | Sí | IndexError |
del lista[i] | Posición o trozo | No | IndexError |
clear() | Todo | No | — |
pop es muy útil para procesar elementos uno a uno, por ejemplo una cola de pedidos.
Buscar: in, index y count
colores = ["rojo", "verde", "azul", "verde"]
print("azul" in colores) # True
print("negro" not in colores) # True
print(colores.index("verde")) # 1: posición de la primera aparición
print(colores.count("verde")) # 2
index lanza ValueError si el valor no está. Por eso conviene comprobar antes con in:
if "negro" in colores:
print(colores.index("negro"))
else:
print("No está")
# No está
Funciones útiles: len, sum, min, max
notas = [7, 9, 5, 8]
print(len(notas)) # 4
print(sum(notas)) # 29
print(max(notas)) # 9
print(min(notas)) # 5
print(sum(notas) / len(notas)) # 7.25 (la media)
min y max también funcionan con textos (orden alfabético). sum solo con números.
Ordenar: sort frente a sorted
Hay dos formas de ordenar y la diferencia es importante:
lista.sort()modifica la propia lista y devuelveNone.sorted(lista)devuelve una lista nueva ordenada y deja la original igual.
notas = [7, 3, 9, 5]
ordenadas = sorted(notas)
print(ordenadas) # [3, 5, 7, 9]
print(notas) # [7, 3, 9, 5] sin cambios
notas.sort(reverse=True) # de mayor a menor
print(notas) # [9, 7, 5, 3]
Usa sorted cuando necesites conservar el orden original, y sort cuando no.
Ordenar con un criterio: key
El parámetro key recibe una función que se aplica a cada elemento para decidir el orden:
nombres = ["eva", "Luis", "ana", "Marta"]
print(sorted(nombres)) # ['Luis', 'Marta', 'ana', 'eva']
print(sorted(nombres, key=str.lower)) # ['ana', 'eva', 'Luis', 'Marta']
print(sorted(nombres, key=len)) # ['eva', 'ana', 'Luis', 'Marta']
Sin key, las mayúsculas van antes que las minúsculas. Con key=str.lower se ordena sin distinguirlas. Para criterios más complejos se usan funciones lambda, que verás en Funciones avanzadas.
Cuidado:
notas = notas.sort()dejanotasvaliendoNone, porquesortno devuelve nada. Es uno de los errores más típicos.
Otros dos métodos: lista.reverse() invierte la lista en su sitio, y reversed(lista) permite recorrerla al revés sin modificarla.
Copiar listas: referencias frente a copias
Esto sorprende a casi todo el mundo la primera vez:
original = ["pan", "leche"]
otra = original # NO es una copia
otra.append("huevos")
print(original)
# ['pan', 'leche', 'huevos']
Una variable no “contiene” la lista, sino que apunta a ella. Con otra = original tienes dos nombres para la misma lista, así que un cambio por un nombre se ve por el otro.
Para obtener una copia independiente:
original = ["pan", "leche"]
copia = original.copy() # también: original[:] o list(original)
copia.append("huevos")
print(original) # ['pan', 'leche']
print(copia) # ['pan', 'leche', 'huevos']
Pasa lo mismo al enviar una lista a una función: si la función la modifica, modifica la original.
Cuidado:
copy()hace una copia superficial. Si la lista contiene otras listas, esas listas interiores siguen compartidas. Para copiarlo todo, usacopy.deepcopy(lista)del módulocopy.
Listas anidadas
Una lista puede contener otras listas. Así se representan tablas o cuadrículas:
notas_clase = [
["Ana", 8, 9],
["Luis", 5, 6],
["Eva", 7, 10],
]
print(notas_clase[1]) # ['Luis', 5, 6]
print(notas_clase[1][0]) # Luis
print(notas_clase[2][2]) # 10
for alumno in notas_clase:
media = (alumno[1] + alumno[2]) / 2
print(f"{alumno[0]}: {media}")
# Ana: 8.5
# Luis: 5.5
# Eva: 8.5
El primer índice elige la fila y el segundo, la columna.
Desempaquetado
Puedes repartir los elementos de una lista entre varias variables:
coordenadas = [40.4, -3.7]
latitud, longitud = coordenadas
print(latitud, longitud)
# 40.4 -3.7
El número de variables debe coincidir con el de elementos; si no, ValueError. Con un asterisco recoges “el resto”:
clasificacion = ["Eva", "Ana", "Luis", "Marta", "Pablo"]
primero, segundo, *resto = clasificacion
print(primero) # Eva
print(resto) # ['Luis', 'Marta', 'Pablo']
Esto se combina muy bien con los bucles: for nombre, nota1, nota2 in notas_clase: desempaqueta cada fila.
Recorrer una lista con enumerate
Para recorrer una lista con su posición, usa enumerate (lo tienes en detalle en Bucles):
podio = ["Eva", "Ana", "Luis"]
for puesto, nombre in enumerate(podio, start=1):
print(f"{puesto}.º {nombre}")
# 1.º Eva
# 2.º Ana
# 3.º Luis
Listas y textos
split convierte un texto en lista y join hace lo contrario:
frase = "aprender a programar"
palabras = frase.split() # ['aprender', 'a', 'programar']
print("-".join(palabras)) # aprender-a-programar
Y para crear una lista a partir de otra en una línea (por ejemplo, los precios con IVA) existen las comprensiones: [p * 1.21 for p in precios]. Tienen su propia lección: Comprensiones de listas.
Errores frecuentes
IndexError: el último índice eslen(lista) - 1, nolen(lista).lista = lista.sort(): deja la variable enNone. Usalista.sort()solo, osorted(lista).- Creer que
b = acopia: usaa.copy(). appendcon una lista cuando queríasextend.removede un valor que no está:ValueError. Comprueba conin.- Borrar mientras recorres:
for x in lista: lista.remove(x)se salta elementos. Recorre una copia o crea una lista nueva.
Resumen
| Tarea | Cómo |
|---|---|
| Crear | [1, 2, 3], [], list(...) |
| Leer / cambiar | lista[0], lista[-1], lista[i] = x |
| Trozo | lista[1:4], lista[:3], lista[::-1] |
| Añadir | append, insert, extend, + |
| Quitar | remove, pop, del, clear |
| Buscar | in, index, count |
| Calcular | len, sum, min, max |
| Ordenar | sort() (en su sitio), sorted() (nueva), key, reverse |
| Copiar | copy(), [:], copy.deepcopy() |
| Desempaquetar | a, b = lista, a, *resto = lista |
Si necesitas una secuencia que no cambie o una colección sin duplicados, sigue con Tuplas y conjuntos.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.