Listas
Listas en Python
Qué es una lista
Una lista es una colección ordenada y mutable de elementos. Es la estructura de datos más versátil y usada en Python. A diferencia de las tuplas, las listas sí se pueden modificar: puedes añadir, eliminar, cambiar y reordenar elementos en cualquier momento.
python
# Una lista puede contener cualquier tipo de dato
numeros = [1, 2, 3, 4, 5]
nombres = ["Ana", "Carlos", "María"]
mixta = ["Python", 42, 3.14, True, None]
anidada = [[1, 2], [3, 4], [5, 6]]
vacia = []
Cómo crear listas
python
# Con corchetes
notas = [8.5, 6.0, 9.2, 7.5]
# Con list()
desde_string = list("Python") # ['P', 'y', 't', 'h', 'o', 'n']
desde_tupla = list((1, 2, 3)) # [1, 2, 3]
desde_rango = list(range(5)) # [0, 1, 2, 3, 4]
desde_set = list({1, 2, 3}) # [1, 2, 3]
# Lista vacía
vacia1 = []
vacia2 = list()
# Lista con elementos repetidos
ceros = [0] * 5 # [0, 0, 0, 0, 0]
patrones = [1, 2] * 3 # [1, 2, 1, 2, 1, 2]
# Con comprensión de lista
cuadrados = [x**2 for x in range(1, 6)] # [1, 4, 9, 16, 25]
Acceso a elementos
python
frutas = ["manzana", "pera", "naranja", "uva", "kiwi"]
# Índices positivos — empiezan en 0
print(frutas[0]) # manzana ← primero
print(frutas[2]) # naranja
print(frutas[4]) # kiwi
# Índices negativos — empiezan en -1 desde el final
print(frutas[-1]) # kiwi ← último
print(frutas[-2]) # uva ← penúltimo
print(frutas[-5]) # manzana ← igual que [0]
# Slicing — extraer sublistas
print(frutas[1:4]) # ['pera', 'naranja', 'uva']
print(frutas[:3]) # ['manzana', 'pera', 'naranja']
print(frutas[2:]) # ['naranja', 'uva', 'kiwi']
print(frutas[::2]) # ['manzana', 'naranja', 'kiwi'] ← uno de cada dos
print(frutas[::-1]) # ['kiwi', 'uva', 'naranja', 'pera', 'manzana'] ← invertida
Modificar elementos
python
notas = [8.5, 6.0, 9.2, 7.5, 5.0]
# Cambiar un elemento
notas[1] = 7.0
print(notas) # [8.5, 7.0, 9.2, 7.5, 5.0]
# Cambiar varios con slicing
notas[0:2] = [9.0, 9.5]
print(notas) # [9.0, 9.5, 9.2, 7.5, 5.0]
# Reemplazar con distinto número de elementos
notas[0:2] = [8.0]
print(notas) # [8.0, 9.2, 7.5, 5.0] ← de 2 elementos pasamos a 1
Métodos para añadir elementos
.append() — añade un elemento al final
python
notas = [8.5, 6.0, 9.2]
notas.append(7.5)
print(notas) # [8.5, 6.0, 9.2, 7.5]
# No devuelve nada (devuelve None)
resultado = notas.append(5.0)
print(resultado) # None
# Uso práctico: recoger datos del usuario
lista_compra = []
while True:
producto = input("Añadir producto (Enter para terminar): ")
if not producto:
break
lista_compra.append(producto)
print(lista_compra)
.insert() — añade en una posición concreta
python
frutas = ["manzana", "pera", "naranja"]
frutas.insert(1, "kiwi") # inserta en posición 1
print(frutas) # ['manzana', 'kiwi', 'pera', 'naranja']
frutas.insert(0, "uva") # inserta al principio
print(frutas) # ['uva', 'manzana', 'kiwi', 'pera', 'naranja']
frutas.insert(100, "limón") # posición mayor que el tamaño → añade al final
print(frutas) # ['uva', 'manzana', 'kiwi', 'pera', 'naranja', 'limón']
.extend() — añade varios elementos de otro iterable
python
lista1 = [1, 2, 3]
lista2 = [4, 5, 6]
lista1.extend(lista2)
print(lista1) # [1, 2, 3, 4, 5, 6]
# También funciona con otros iterables
lista1.extend((7, 8)) # desde tupla
lista1.extend(range(9, 11)) # desde rango
lista1.extend("ab") # desde string → añade 'a' y 'b' por separado
print(lista1) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'a', 'b']
# Diferencia con append
lista = [1, 2, 3]
lista.append([4, 5]) # añade la lista como un solo elemento
print(lista) # [1, 2, 3, [4, 5]] ← lista anidada
lista = [1, 2, 3]
lista.extend([4, 5]) # añade cada elemento por separado
print(lista) # [1, 2, 3, 4, 5]
# Forma alternativa con +=
lista = [1, 2, 3]
lista += [4, 5]
print(lista) # [1, 2, 3, 4, 5]
Métodos para eliminar elementos
.remove() — elimina por valor
python
frutas = ["manzana", "pera", "naranja", "pera", "kiwi"]
frutas.remove("pera") # elimina la PRIMERA aparición
print(frutas) # ['manzana', 'naranja', 'pera', 'kiwi']
# Si no existe lanza ValueError
try:
frutas.remove("uva")
except ValueError:
print("uva no está en la lista")
# Uso práctico: eliminar un elemento si existe
def eliminar_si_existe(lista, elemento):
if elemento in lista:
lista.remove(elemento)
return True
return False
carrito = ["laptop", "ratón", "teclado"]
eliminado = eliminar_si_existe(carrito, "ratón")
print(f"Eliminado: {eliminado}") # Eliminado: True
print(carrito) # ['laptop', 'teclado']
.pop() — elimina por índice y devuelve el elemento
python
frutas = ["manzana", "pera", "naranja", "uva"]
# Sin argumento elimina el último
ultimo = frutas.pop()
print(ultimo) # uva
print(frutas) # ['manzana', 'pera', 'naranja']
# Con índice elimina ese elemento
segundo = frutas.pop(1)
print(segundo) # pera
print(frutas) # ['manzana', 'naranja']
# Uso práctico: procesar elementos uno a uno
pila = [1, 2, 3, 4, 5]
while pila:
elemento = pila.pop() # procesa del último al primero
print(f"Procesando: {elemento}")
.clear() — vacía la lista completamente
python
notas = [8.5, 6.0, 9.2, 7.5]
notas.clear()
print(notas) # []
print(len(notas)) # 0
# Diferente a reasignar
lista = [1, 2, 3]
referencia = lista
lista.clear()
print(referencia) # [] ← también vacía porque apuntan al mismo objeto
lista = [1, 2, 3]
referencia = lista
lista = [] # esto crea una nueva lista, no vacía la original
print(referencia) # [1, 2, 3] ← intacta
del — elimina por índice o slicing
python
frutas = ["manzana", "pera", "naranja", "uva", "kiwi"]
del frutas[1] # elimina el índice 1
print(frutas) # ['manzana', 'naranja', 'uva', 'kiwi']
del frutas[1:3] # elimina del índice 1 al 2
print(frutas) # ['manzana', 'kiwi']
del frutas # elimina la variable completamente
# print(frutas) # NameError: frutas no existe
Métodos de búsqueda e información
.index() — posición de un elemento
python
frutas = ["manzana", "pera", "naranja", "pera"]
print(frutas.index("pera")) # 1 ← primera aparición
print(frutas.index("pera", 2)) # 3 ← busca desde posición 2
try:
frutas.index("kiwi")
except ValueError:
print("kiwi no encontrado")
.count() — cuántas veces aparece un elemento
python
notas = [8.5, 6.0, 8.5, 9.2, 6.0, 8.5]
print(notas.count(8.5)) # 3
print(notas.count(6.0)) # 2
print(notas.count(10.0)) # 0
# Uso práctico
resultados = ["victoria", "derrota", "victoria", "empate", "victoria"]
victorias = resultados.count("victoria")
derrotas = resultados.count("derrota")
empates = resultados.count("empate")
print(f"V:{victorias} D:{derrotas} E:{empates}") # V:3 D:1 E:1
in y not in — comprobar pertenencia
python
frutas = ["manzana", "pera", "naranja"]
print("pera" in frutas) # True
print("kiwi" in frutas) # False
print("kiwi" not in frutas) # True
# Uso práctico
def verificar_acceso(usuario, usuarios_permitidos):
return usuario in usuarios_permitidos
permitidos = ["ana", "carlos", "maría"]
print(verificar_acceso("ana", permitidos)) # True
print(verificar_acceso("pedro", permitidos)) # False
Métodos de ordenación
.sort() — ordena la lista en sitio
Modifica la lista original y no devuelve nada.
python
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
numeros.sort()
print(numeros) # [1, 1, 2, 3, 4, 5, 6, 9]
numeros.sort(reverse=True)
print(numeros) # [9, 6, 5, 4, 3, 2, 1, 1]
# Ordenar strings
nombres = ["Carlos", "ana", "María", "pedro"]
nombres.sort()
print(nombres) # ['Carlos', 'María', 'ana', 'pedro'] ← mayúsculas primero
nombres.sort(key=str.lower)
print(nombres) # ['ana', 'Carlos', 'María', 'pedro'] ← orden correcto
# Con key personalizado
alumnos = [
{"nombre": "Carlos", "nota": 6.0},
{"nombre": "Ana", "nota": 9.2},
{"nombre": "María", "nota": 7.5},
]
alumnos.sort(key=lambda a: a["nota"])
for a in alumnos:
print(f"{a['nombre']}: {a['nota']}")
# Carlos: 6.0
# María: 7.5
# Ana: 9.2
.reverse() — invierte el orden
python
lista = [1, 2, 3, 4, 5]
lista.reverse()
print(lista) # [5, 4, 3, 2, 1]
# No devuelve nada, modifica en sitio
resultado = lista.reverse()
print(resultado) # None
Copia de listas
python
original = [1, 2, 3, 4, 5]
# Asignación — NO es una copia, apuntan al mismo objeto
referencia = original
referencia[0] = 99
print(original) # [99, 2, 3, 4, 5] ← también cambia
# Copia superficial — sí es una copia
copia1 = original.copy()
copia2 = original[:]
copia3 = list(original)
copia1[0] = 0
print(original) # [99, 2, 3, 4, 5] ← no cambia
print(copia1) # [0, 2, 3, 4, 5]
# Copia profunda — para listas anidadas
import copy
anidada = [[1, 2], [3, 4], [5, 6]]
copia_superficial = anidada.copy()
copia_profunda = copy.deepcopy(anidada)
anidada[0][0] = 99
print(copia_superficial) # [[99, 2], [3, 4], [5, 6]] ← afectada
print(copia_profunda) # [[1, 2], [3, 4], [5, 6]] ← intacta
Comprensiones de lista
Las comprensiones de lista son la forma más pythónica de crear listas. Son más rápidas y concisas que los bucles equivalentes.
Sintaxis básica
python
# Forma larga con bucle
cuadrados = []
for n in range(1, 6):
cuadrados.append(n**2)
# Comprensión de lista
cuadrados = [n**2 for n in range(1, 6)]
print(cuadrados) # [1, 4, 9, 16, 25]
Con condición
python
# Solo los pares
pares = [n for n in range(1, 21) if n % 2 == 0]
print(pares) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# Solo notas aprobadas
notas = [8.5, 4.8, 9.2, 3.0, 7.5, 5.0]
aprobadas = [n for n in notas if n >= 5]
print(aprobadas) # [8.5, 9.2, 7.5, 5.0]
# Filtrar y transformar
mayusculas = [p.upper() for p in ["ana", "carlos", "maría"] if len(p) > 4]
print(mayusculas) # ['CARLOS', 'MARÍA']
Con condición ternaria
python
notas = [8.5, 4.8, 9.2, 3.0, 7.5]
estados = ["Aprobado" if n >= 5 else "Suspenso" for n in notas]
print(estados) # ['Aprobado', 'Suspenso', 'Aprobado', 'Suspenso', 'Aprobado']
Comprensiones anidadas
python
# Tabla de multiplicar como lista de listas
tabla = [[i*j for j in range(1, 6)] for i in range(1, 6)]
for fila in tabla:
print(fila)
# [1, 2, 3, 4, 5]
# [2, 4, 6, 8, 10]
# [3, 6, 9, 12, 15]
# [4, 8, 12, 16, 20]
# [5, 10, 15, 20, 25]
# Aplanar lista de listas
anidada = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
plana = [n for sublista in anidada for n in sublista]
print(plana) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Listas anidadas — matrices
python
# Crear una matriz 3x3
matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Acceder a elementos
print(matriz[0][0]) # 1 ← fila 0, columna 0
print(matriz[1][2]) # 6 ← fila 1, columna 2
print(matriz[2][1]) # 8 ← fila 2, columna 1
# Recorrer
for fila in matriz:
for elemento in fila:
print(elemento, end=" ")
print()
# 1 2 3
# 4 5 6
# 7 8 9
# Modificar
matriz[1][1] = 99
print(matriz[1]) # [4, 99, 6]
# Transponer (filas ↔ columnas)
transpuesta = [[fila[i] for fila in matriz] for i in range(len(matriz[0]))]
for fila in transpuesta:
print(fila)
Operaciones frecuentes
Eliminar duplicados conservando el orden
python
def eliminar_duplicados(lista):
vistos = set()
resultado = []
for elemento in lista:
if elemento not in vistos:
vistos.add(elemento)
resultado.append(elemento)
return resultado
ciudades = ["Madrid", "Barcelona", "Madrid", "Valencia", "Barcelona", "Sevilla"]
print(eliminar_duplicados(ciudades))
# ['Madrid', 'Barcelona', 'Valencia', 'Sevilla']
# Forma rápida sin preservar orden
sin_duplicados = list(set(ciudades))
print(sin_duplicados) # orden no garantizado
Aplanar lista de listas
python
def aplanar(lista_anidada):
resultado = []
for sublista in lista_anidada:
resultado.extend(sublista)
return resultado
grupos = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
print(aplanar(grupos)) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Con comprensión
plana = [x for grupo in grupos for x in grupo]
print(plana) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Buscar el índice de todos los que cumplen una condición
python
notas = [8.5, 4.8, 9.2, 3.0, 7.5, 4.5, 9.0]
# Índices de suspensos
indices_suspensos = [i for i, n in enumerate(notas) if n < 5]
print(indices_suspensos) # [1, 3, 5]
# Índices y valores
suspensos = [(i, n) for i, n in enumerate(notas) if n < 5]
print(suspensos) # [(1, 4.8), (3, 3.0), (5, 4.5)]
Dividir una lista en grupos
python
def dividir_en_grupos(lista, tamaño):
return [lista[i:i+tamaño] for i in range(0, len(lista), tamaño)]
alumnos = ["Ana", "Carlos", "María", "Pedro", "Lucía", "Juan", "Rosa"]
grupos = dividir_en_grupos(alumnos, 3)
for i, grupo in enumerate(grupos, 1):
print(f"Grupo {i}: {grupo}")
# Grupo 1: ['Ana', 'Carlos', 'María']
# Grupo 2: ['Pedro', 'Lucía', 'Juan']
# Grupo 3: ['Rosa']
Rotar una lista
python
def rotar(lista, n):
n = n % len(lista)
return lista[n:] + lista[:n]
nums = [1, 2, 3, 4, 5]
print(rotar(nums, 2)) # [3, 4, 5, 1, 2]
print(rotar(nums, -1)) # [5, 1, 2, 3, 4]
Ejemplo práctico completo — sistema de gestión de alumnos
python
def crear_alumno(nombre, notas):
return {"nombre": nombre, "notas": notas}
def media(notas):
return round(sum(notas) / len(notas), 2) if notas else 0
def calificacion(nota):
if nota >= 9: return "Sobresaliente"
elif nota >= 7: return "Notable"
elif nota >= 5: return "Aprobado"
else: return "Suspenso"
def añadir_nota(alumno, nota):
if 0 <= nota <= 10:
alumno["notas"].append(nota)
return True
return False
def informe_clase(alumnos):
print(f"\n{'='*55}")
print(f" INFORME DE CLASE")
print(f"{'='*55}")
print(f" {'Nombre':<15} {'Notas':<22} {'Media':>6} {'Calific.'}")
print(f" {'─'*53}")
medias = []
for alumno in sorted(alumnos, key=lambda a: media(a["notas"]), reverse=True):
m = media(alumno["notas"])
calif = calificacion(m)
notas_str = str(alumno["notas"])
medias.append(m)
print(f" {alumno['nombre']:<15} {notas_str:<22} {m:>6} {calif}")
print(f" {'─'*53}")
print(f" Media de la clase: {media(medias):.2f}")
aprobados = sum(1 for m in medias if m >= 5)
print(f" Aprobados: {aprobados}/{len(alumnos)}")
print(f" Mejor nota media: {max(medias)}")
print(f" Peor nota media: {min(medias)}")
print(f"{'='*55}")
# Uso
alumnos = [
crear_alumno("Ana García", [8.5, 9.0, 7.8]),
crear_alumno("Carlos López", [4.8, 5.5, 6.0]),
crear_alumno("María Ruiz", [9.5, 9.8, 9.1]),
crear_alumno("Pedro Sanz", [5.0, 6.5, 4.8]),
]
añadir_nota(alumnos[0], 9.2)
añadir_nota(alumnos[2], 8.7)
informe_clase(alumnos)
```
Salida:
```
=======================================================
INFORME DE CLASE
=======================================================
Nombre Notas Media Calific.
─────────────────────────────────────────────────────
María Ruiz [9.5, 9.8, 9.1, 8.7] 9.28 Sobresaliente
Ana García [8.5, 9.0, 7.8, 9.2] 8.63 Notable
Carlos López [4.8, 5.5, 6.0] 5.43 Aprobado
Pedro Sanz [5.0, 6.5, 4.8] 5.43 Aprobado
─────────────────────────────────────────────────────
Media de la clase: 7.19
Aprobados: 4/4
Mejor nota media: 9.28
Peor nota media: 5.43
=======================================================
Resumen de métodos
| Método | Qué hace | Modifica original | Devuelve |
|---|---|---|---|
.append(x) |
Añade x al final | Sí | None |
.insert(i, x) |
Inserta x en posición i | Sí | None |
.extend(iter) |
Añade todos los elementos de iter | Sí | None |
.remove(x) |
Elimina la primera aparición de x | Sí | None |
.pop(i) |
Elimina y devuelve el elemento i | Sí | Elemento |
.clear() |
Vacía la lista | Sí | None |
.index(x) |
Posición de la primera aparición de x | No | int |
.count(x) |
Cuántas veces aparece x | No | int |
.sort() |
Ordena en sitio | Sí | None |
.reverse() |
Invierte en sitio | Sí | None |
.copy() |
Copia superficial | No | list |