Colecciones que cambian

6 ejercicios para trabajar con listas en Python

Escribe funciones que puedas comprobar. Cada ejercicio trae un contrato claro, pruebas con assert, una pista y una solución explicada que abres cuando quieras.

6 ejercicios progresivosPistas y solucionesPruebas con assert

Cómo practicar con estos ejercicios de listas

Necesitas conocer las listas, los índices y el bucle for. Los últimos ejercicios usan también slicing.

  1. Lee el contrato: qué recibe la función y qué debe devolver.
  2. Escribe la función y añade debajo las comprobaciones.
  3. Ejecuta ambas partes. Un assert que pasa no imprime nada; si falla, aparece AssertionError.
  4. Antes de abrir la solución, prueba una lista vacía y una de un solo elemento: son los casos que más fallos esconden.
Las funciones devuelven, no imprimen.

Cada solución usa return. Mostrar un valor con print no sustituye al resultado que espera recibir quien llama a la función.

Todas las soluciones incluyen sus pruebas y puedes abrirlas en el editor con el botón «Probar en el editor». Las comprobaciones son educativas y no sustituyen toda la validación de una aplicación real.

Nivel 1

Leer y recorrer

Ejercicio 01

Devuelve el último elemento

Escribe ultimo(lista). Devuelve el último elemento de una lista o None si está vacía.

Comprobaciones · añade tu función antes
assert ultimo([1, 2, 3]) == 3
assert ultimo(["a"]) == "a"
assert ultimo([]) is None
Ver una pista para el ejercicio 1

Una lista vacía no tiene índice -1. Comprueba si hay elementos antes de leer.

Ver solución y explicación del ejercicio 1
Solución completa · ejercicio 01
def ultimo(lista):
    if not lista:
        return None
    return lista[-1]

assert ultimo([1, 2, 3]) == 3
assert ultimo(["a"]) == "a"
assert ultimo([]) is None
print("Pruebas superadas")

Una lista vacía se considera falsa en una condición. Sin la comprobación, ultimo([]) produciría IndexError.

Ejercicio 02

Calcula la media de una lista

Escribe media(numeros). Devuelve la media de una lista de números o None si la lista está vacía.

Comprobaciones · añade tu función antes
assert media([2, 4, 6]) == 4
assert media([5]) == 5
assert media([-1, 1]) == 0
assert media([]) is None
Ver una pista para el ejercicio 2

Suma con un acumulador o con sum y divide por la longitud, pero solo cuando haya elementos.

Ver solución y explicación del ejercicio 2
Solución completa · ejercicio 02
def media(numeros):
    if not numeros:
        return None
    return sum(numeros) / len(numeros)

assert media([2, 4, 6]) == 4
assert media([5]) == 5
assert media([-1, 1]) == 0
assert media([]) is None
print("Pruebas superadas")

Dividir entre len([]) produciría ZeroDivisionError, así que el caso vacío se decide antes de calcular.

Nivel 2

Construir listas nuevas

Ejercicio 03

Filtra los números negativos

Escribe sin_negativos(numeros). Devuelve una lista nueva con los números mayores o iguales que cero, conservando el orden. No modifica la lista recibida.

Comprobaciones · añade tu función antes
entrada = [3, -1, 0, -5, 8]
assert sin_negativos(entrada) == [3, 0, 8]
assert entrada == [3, -1, 0, -5, 8]
assert sin_negativos([]) == []
assert sin_negativos([-1, -2]) == []
Ver una pista para el ejercicio 3

Crea una lista vacía y añade solo los valores que cumplan la condición.

Ver solución y explicación del ejercicio 3
Solución completa · ejercicio 03
def sin_negativos(numeros):
    resultado = []
    for numero in numeros:
        if numero >= 0:
            resultado.append(numero)
    return resultado

entrada = [3, -1, 0, -5, 8]
assert sin_negativos(entrada) == [3, 0, 8]
assert entrada == [3, -1, 0, -5, 8]
assert sin_negativos([]) == []
assert sin_negativos([-1, -2]) == []
print("Pruebas superadas")

La lista nueva protege la entrada original. El cero se conserva porque la condición dice mayor o igual.

Ejercicio 04

Invierte una lista sin modificarla

Escribe invertir(lista). Devuelve una lista nueva con los elementos en orden inverso. La lista original no cambia.

Comprobaciones · añade tu función antes
original = [1, 2, 3]
assert invertir(original) == [3, 2, 1]
assert original == [1, 2, 3]
assert invertir([]) == []
assert invertir(["a"]) == ["a"]
Ver una pista para el ejercicio 4

Un slice con paso -1 crea una copia al revés. El método reverse modifica la lista original y devuelve None.

Ver solución y explicación del ejercicio 4
Solución completa · ejercicio 04
def invertir(lista):
    return lista[::-1]

original = [1, 2, 3]
assert invertir(original) == [3, 2, 1]
assert original == [1, 2, 3]
assert invertir([]) == []
assert invertir(["a"]) == ["a"]
print("Pruebas superadas")

lista[::-1] recorre de final a inicio y produce un objeto nuevo. Si hubieras usado lista.reverse(), la prueba de la entrada original fallaría.

Nivel 3

Combinar y transformar

Ejercicio 05

Une dos listas sin repetidos

Escribe unir_sin_repetir(a, b). Devuelve una lista con los elementos de a y después los de b que aún no estén, sin repeticiones y en orden de aparición.

Comprobaciones · añade tu función antes
assert unir_sin_repetir([1, 2], [2, 3]) == [1, 2, 3]
assert unir_sin_repetir([], [1, 1]) == [1]
assert unir_sin_repetir([1, 1], []) == [1]
assert unir_sin_repetir(["a"], ["b", "a"]) == ["a", "b"]
Ver una pista para el ejercicio 5

Construye el resultado paso a paso y pregunta con in antes de añadir. Un set no conserva el orden.

Ver solución y explicación del ejercicio 5
Solución completa · ejercicio 05
def unir_sin_repetir(a, b):
    resultado = []
    for elemento in a + b:
        if elemento not in resultado:
            resultado.append(elemento)
    return resultado

assert unir_sin_repetir([1, 2], [2, 3]) == [1, 2, 3]
assert unir_sin_repetir([], [1, 1]) == [1]
assert unir_sin_repetir([1, 1], []) == [1]
assert unir_sin_repetir(["a"], ["b", "a"]) == ["a", "b"]
print("Pruebas superadas")

a + b crea una lista temporal con todos los elementos. Preguntar por pertenencia en el resultado conserva la primera aparición y el orden.

Ejercicio 06

Rota los elementos hacia la izquierda

Escribe rotar(lista, k). Devuelve una lista nueva con los elementos desplazados k posiciones hacia la izquierda; los primeros pasan al final. k puede ser mayor que la longitud y una lista vacía devuelve [].

Comprobaciones · añade tu función antes
assert rotar([1, 2, 3, 4], 1) == [2, 3, 4, 1]
assert rotar([1, 2, 3, 4], 5) == [2, 3, 4, 1]
assert rotar([1, 2, 3], 0) == [1, 2, 3]
assert rotar([], 3) == []
Ver una pista para el ejercicio 6

Cuando k supera la longitud, solo importa el resto de dividir k entre len(lista). Combina dos slices.

Ver solución y explicación del ejercicio 6
Solución completa · ejercicio 06
def rotar(lista, k):
    if not lista:
        return []
    k = k % len(lista)
    return lista[k:] + lista[:k]

assert rotar([1, 2, 3, 4], 1) == [2, 3, 4, 1]
assert rotar([1, 2, 3, 4], 5) == [2, 3, 4, 1]
assert rotar([1, 2, 3], 0) == [1, 2, 3]
assert rotar([], 3) == []
print("Pruebas superadas")

El resto k % len(lista) evita giros completos innecesarios. Con una lista vacía esa división produciría ZeroDivisionError, así que se resuelve antes.

Errores frecuentes en estos ejercicios

IndexError al leer una posición
Pides un índice que no existe, a menudo en una lista vacía. Consulta IndexError y comprueba la longitud antes de leer.
La lista original cambia
Métodos como sort, reverse o append modifican la lista recibida. Si el contrato pide una lista nueva, construye una copia.
Se guarda None en lugar de una lista
Esos métodos devuelven None. No reasignes su retorno a la variable: lista = lista.append(x) destruye la lista.
La función falla con lista vacía
Decide qué debe devolver antes de calcular: None, una lista vacía o un error son contratos distintos.

Si no entiendes el traceback, empieza por su última línea en la guía de errores de Python.

Preguntas frecuentes sobre ejercicios de listas

¿Debo modificar la lista que recibo o crear una nueva?

Lo que diga el contrato. En estos ejercicios se crea una lista nueva para que quien llama conserve su entrada original.

¿Cuándo uso slicing y cuándo un bucle?

El slicing es ideal para tramos y copias. Un bucle es mejor cuando necesitas decidir elemento a elemento.

¿Puedo usar list comprehensions?

Sí, cuando puedas explicar la transformación en una frase. Si el bucle explícito te resulta más claro, úsalo: es una solución igual de válida.

Consulta datos por su nombre

Las listas se consultan por posición; los diccionarios, por nombre del dato.

Practicar diccionarios →Ver los 12 ejercicios de fundamentos

Fuentes y compatibilidad

Los ejemplos usan Python 3 y la biblioteca estándar. Las instrucciones de instalación se contrastaron con la documentación oficial; los ejemplos de código se verifican con las comprobaciones de estas guías.

Consulta la metodología y las versiones del editor.