Funciones en Python — ejercicios para afianzar lo que sabes
Las funciones en Python ejercicios con solución son el cierre perfecto de este tema. Ya viste la teoría y practicaste con programas reales. Ahora toca resolver por tu cuenta. Cuatro ejercicios en tres niveles con especial atención al error más silencioso de todos: olvidar el return y trabajar sin darte cuenta con None.
Como siempre: intenta resolverlo, usa la pista si llevas más de 10 minutos atascado, compara con la solución comentada al final y usa pythontutor.com
Tabla de Contenidos
Funciones en Python ejercicios — Nivel Básico
Ejercicio 1 — Conversor de notas entre sistemas
Escribe un conjunto de funciones que conviertan notas entre tres sistemas diferentes: el sistema español (0-10), el sistema americano (0-100) y el sistema de letras americano (A, B, C, D, F).
Las conversiones son:
- Española → Americana: multiplica por 10
- Americana → Española: divide entre 10
- Española → Letra: 9-10=A, 7-8=B, 5-6=C, 3-4=D, 0-2=F
- Letra → Española: A=9.5, B=7.5, C=5.5, D=3.5, F=1.5
La salida debe ser:
=== CONVERSOR DE NOTAS === Nota española (0-10): 7.5 --- Conversiones --- Sistema español: 7.5 Sistema americano: 75.0 Sistema de letras: B
💡 Pista — el error del return: Cada función debe devolver el valor con return, no imprimirlo con print. Si usas print dentro de la función y luego intentas hacer nota_americana = española_a_americana(7.5), la variable valdrá None aunque veas el número en pantalla. La función imprime pero no devuelve nada. Siempre return.
Ejercicio 2 — Generador de informe de notas
Usando las funciones del ejercicio anterior, escribe un programa que pida las notas de 4 asignaturas y genere un informe completo con la media, la nota más alta, la más baja y la conversión de cada nota a los tres sistemas.
=== INFORME DE NOTAS === Asignatura 1: FP1 Nota (0-10): 8.5 Asignatura 2: Estadística Nota (0-10): 7.0 Asignatura 3: Matemáticas Nota (0-10): 6.5 Asignatura 4: Bases de datos Nota (0-10): 9.0 --- Informe completo --- FP1: 8.5 | 85.0 | A Estadística: 7.0 | 70.0 | B Matemáticas: 6.5 | 65.0 | C Bases de datos: 9.0 | 90.0 | A Media: 7.75 → B Más alta: 9.0 (Bases de datos) Más baja: 6.5 (Matemáticas)
💡 Pista: Reutiliza las funciones del ejercicio anterior, eso es exactamente para lo que sirven. Crea una función pedir_asignatura() que pida nombre y nota y devuelva ambos. Crea otra función generar_informe(asignaturas) que reciba la lista y genere el resumen. El error del return aquí aparece si pedir_asignatura() hace print en vez de return, luego no puedes guardar los datos.
Funciones en Python ejercicios — Nivel Intermedio
Ejercicio 3 — Mini banco con funciones
Simula un sistema bancario básico con funciones para cada operación. El banco debe permitir consultar saldo, depositar dinero, retirar dinero y ver el historial de movimientos.
=== BANCO SERGIO LEARNS === Saldo inicial: 1000.0 € 1. Consultar saldo 2. Depositar 3. Retirar 4. Ver historial 0. Salir Opción: 2 Cantidad a depositar: 500 ✓ Depósito realizado: +500.0 € Saldo actual: 1500.0 € Opción: 3 Cantidad a retirar: 200 ✓ Retirada realizada: -200.0 € Saldo actual: 1300.0 € Opción: 4 --- Historial de movimientos --- Saldo inicial: +1000.0 € Depósito: +500.0 € Retirada: -200.0 € ───────────────────────────── Saldo actual: 1300.0 €
💡 Pistas:
- Crea estas funciones:
consultar_saldo(saldo),depositar(saldo, cantidad),retirar(saldo, cantidad),mostrar_historial(historial),menu_banco() - Las funciones
depositaryretirardeben devolver el nuevo saldo, ese es elreturnclave. Si olvidas elreturnel saldo nunca se actualiza aunque la función parezca funcionar - Guarda el historial como una lista de strings que vas actualizando con cada operación
retirardebe comprobar que hay saldo suficiente antes de retirar
Funciones en Python ejercicios — Desafío Final
Ejercicio 4 — Juego de dados con estadísticas
Simula un juego de dados donde el jugador lanza dos dados un número determinado de veces. El programa debe mostrar cada lanzamiento y al final generar estadísticas completas.
=== JUEGO DE DADOS === ¿Cuántos lanzamientos? 5 Lanzamiento 1: 🎲 3 + 🎲 5 = 8 Lanzamiento 2: 🎲 6 + 🎲 6 = 12 ← ¡Doble! Lanzamiento 3: 🎲 2 + 🎲 4 = 6 Lanzamiento 4: 🎲 1 + 🎲 1 = 2 ← ¡Doble! Lanzamiento 5: 🎲 4 + 🎲 3 = 7 --- Estadísticas --- Total lanzamientos: 5 Suma total: 35 Media por lanzamiento: 7.0 Máximo obtenido: 12 (lanzamiento 2) Mínimo obtenido: 2 (lanzamiento 4) Dobles conseguidos: 2 (40.0%) Distribución de resultados: 2: ██ (1 vez) 6: ██ (1 vez) 7: ██ (1 vez) 8: ██ (1 vez) 12: ██ (1 vez)
💡 Pistas:
- Crea estas funciones:
lanzar_dado(),lanzar_dos_dados(),es_doble(dado1, dado2),calcular_estadisticas(resultados),mostrar_distribucion(resultados),jugar() lanzar_dado()debe devolver el valor — si usaprinten vez dereturnno podrás sumar los dadoslanzar_dos_dados()debe devolver una tupla(dado1, dado2)— así puedes desempaquetar cond1, d2 = lanzar_dos_dados()- Para la distribución usa un diccionario donde la clave es el resultado y el valor es cuántas veces apareció
- Los bloques de la distribución se hacen con
"█" * cantidad
Soluciones Comentadas
Solución Ejercicio 1:
# Conversor de notas entre sistemas
def española_a_americana(nota):
return round(nota * 10, 1)
def americana_a_española(nota):
return round(nota / 10, 1)
def española_a_letra(nota):
if nota >= 9:
return "A"
elif nota >= 7:
return "B"
elif nota >= 5:
return "C"
elif nota >= 3:
return "D"
else:
return "F"
def letra_a_española(letra):
equivalencias = {"A": 9.5, "B": 7.5, "C": 5.5, "D": 3.5, "F": 1.5}
return equivalencias.get(letra.upper(), None)
def mostrar_conversiones(nota_española):
americana = española_a_americana(nota_española)
letra = española_a_letra(nota_española)
print(f"\n--- Conversiones ---")
print(f"Sistema español: {nota_española}")
print(f"Sistema americano: {americana}")
print(f"Sistema de letras: {letra}")
print("=== CONVERSOR DE NOTAS ===")
nota = float(input("Nota española (0-10): "))
if nota < 0 or nota > 10:
print("Error: la nota debe estar entre 0 y 10")
else:
mostrar_conversiones(nota)
Solución Ejercicio 2:
# Informe de notas — reutiliza funciones del ejercicio 1
def pedir_asignatura(numero):
nombre = input(f"Asignatura {numero}: ")
nota = float(input(f"Nota (0-10): "))
while nota < 0 or nota > 10:
print("Error: entre 0 y 10")
nota = float(input(f"Nota (0-10): "))
return nombre, nota
def generar_informe(asignaturas):
print("\n--- Informe completo ---")
notas = []
for nombre, nota in asignaturas:
americana = española_a_americana(nota)
letra = española_a_letra(nota)
print(f"{nombre:<20} {nota} | {americana} | {letra}")
notas.append(nota)
media = round(sum(notas) / len(notas), 2)
nota_max = max(notas)
nota_min = min(notas)
nombre_max = asignaturas[notas.index(nota_max)][0]
nombre_min = asignaturas[notas.index(nota_min)][0]
print(f"\nMedia: {media} → {española_a_letra(media)}")
print(f"Más alta: {nota_max} ({nombre_max})")
print(f"Más baja: {nota_min} ({nombre_min})")
print("=== INFORME DE NOTAS ===\n")
asignaturas = []
for i in range(1, 5):
nombre, nota = pedir_asignatura(i)
asignaturas.append((nombre, nota))
print()
generar_informe(asignaturas)
Solución Ejercicio 3:
# Mini banco con funciones
def consultar_saldo(saldo):
print(f"\nSaldo actual: {saldo} €")
def depositar(saldo, cantidad):
if cantidad <= 0:
print("Error: la cantidad debe ser positiva")
return saldo # devuelve el saldo sin cambios
nuevo_saldo = round(saldo + cantidad, 2)
print(f"✓ Depósito realizado: +{cantidad} €")
print(f"Saldo actual: {nuevo_saldo} €")
return nuevo_saldo # RETURN clave — devuelve el nuevo saldo
def retirar(saldo, cantidad):
if cantidad <= 0:
print("Error: la cantidad debe ser positiva")
return saldo
if cantidad > saldo:
print(f"Error: saldo insuficiente. Tienes {saldo} €")
return saldo
nuevo_saldo = round(saldo - cantidad, 2)
print(f"✓ Retirada realizada: -{cantidad} €")
print(f"Saldo actual: {nuevo_saldo} €")
return nuevo_saldo
def mostrar_historial(historial, saldo):
print("\n--- Historial de movimientos ---")
for movimiento in historial:
print(movimiento)
print("─" * 33)
print(f"Saldo actual: {saldo} €")
def menu_banco():
print("=== BANCO SERGIO LEARNS ===\n")
saldo_inicial = float(input("Saldo inicial: "))
saldo = saldo_inicial
historial = [f"Saldo inicial: +{saldo_inicial} €"]
while True:
print("\n1. Consultar saldo")
print("2. Depositar")
print("3. Retirar")
print("4. Ver historial")
print("0. Salir")
opcion = input("\nOpción: ")
if opcion == "0":
print("Hasta pronto")
break
elif opcion == "1":
consultar_saldo(saldo)
elif opcion == "2":
cantidad = float(input("Cantidad a depositar: "))
saldo_anterior = saldo
saldo = depositar(saldo, cantidad)
if saldo != saldo_anterior:
historial.append(f"Depósito: +{cantidad} €")
elif opcion == "3":
cantidad = float(input("Cantidad a retirar: "))
saldo_anterior = saldo
saldo = retirar(saldo, cantidad)
if saldo != saldo_anterior:
historial.append(f"Retirada: -{cantidad} €")
elif opcion == "4":
mostrar_historial(historial, saldo)
else:
print("Opción no válida")
menu_banco()
Solución Ejercicio 4:
# Juego de dados con estadísticas
import random
def lanzar_dado():
return random.randint(1, 6) # RETURN — devuelve el valor
def lanzar_dos_dados():
return lanzar_dado(), lanzar_dado() # devuelve tupla
def es_doble(dado1, dado2):
return dado1 == dado2
def calcular_estadisticas(resultados):
sumas = [d1 + d2 for d1, d2 in resultados]
dobles = sum(1 for d1, d2 in resultados if es_doble(d1, d2))
return {
"total": len(resultados),
"suma_total": sum(sumas),
"media": round(sum(sumas) / len(sumas), 2),
"maximo": max(sumas),
"lanz_max": sumas.index(max(sumas)) + 1,
"minimo": min(sumas),
"lanz_min": sumas.index(min(sumas)) + 1,
"dobles": dobles,
"pct_dobles": round(dobles / len(resultados) * 100, 1),
"sumas": sumas
}
def mostrar_distribucion(sumas):
print("Distribución de resultados:")
conteo = {}
for s in sumas:
conteo[s] = conteo.get(s, 0) + 1
for valor in sorted(conteo.keys()):
barra = "█" * conteo[valor]
print(f" {valor:2d}: {barra} ({conteo[valor]} vez)")
def jugar():
print("=== JUEGO DE DADOS ===")
n = int(input("¿Cuántos lanzamientos? "))
resultados = []
print()
for i in range(1, n + 1):
d1, d2 = lanzar_dos_dados()
suma = d1 + d2
doble = " ← ¡Doble!" if es_doble(d1, d2) else ""
print(f"Lanzamiento {i}: 🎲 {d1} + 🎲 {d2} = {suma}{doble}")
resultados.append((d1, d2))
stats = calcular_estadisticas(resultados)
print(f"\n--- Estadísticas ---")
print(f"Total lanzamientos: {stats['total']}")
print(f"Suma total: {stats['suma_total']}")
print(f"Media por lanzamiento: {stats['media']}")
print(f"Máximo obtenido: {stats['maximo']} (lanzamiento {stats['lanz_max']})")
print(f"Mínimo obtenido: {stats['minimo']} (lanzamiento {stats['lanz_min']})")
print(f"Dobles conseguidos: {stats['dobles']} ({stats['pct_dobles']}%)")
mostrar_distribucion(stats['sumas'])
jugar()
💡 Nota: aquí usamos listas y diccionarios que veremos en profundidad en el próximos tema. Por ahora trátalo como una colección de valores.
Chuletario — Funciones en Python
# ============================================
# CHULETARIO — Funciones en Python
# Sergio Learns · sergiolearns.com
# ============================================
# DEFINIR UNA FUNCIÓN
def nombre_funcion(parametro1, parametro2):
# cuerpo
return resultado
# LLAMAR A UNA FUNCIÓN
resultado = nombre_funcion(argumento1, argumento2)
# PARÁMETRO vs ARGUMENTO
def saludar(nombre): # nombre = PARÁMETRO (en la definición)
return f"Hola, {nombre}"
saludar("Sergio") # "Sergio" = ARGUMENTO (en la llamada)
# PARÁMETROS CON VALOR POR DEFECTO
def saludar(nombre, saludo="Hola"):
return f"{saludo}, {nombre}"
saludar("Sergio") # → "Hola, Sergio"
saludar("Sergio", "Buenos días") # → "Buenos días, Sergio"
# RETURN — devuelve valor Y termina la función
def sumar(a, b):
return a + b # termina aquí
print("nunca") # código muerto — nunca se ejecuta
# SIN RETURN → devuelve None
def imprimir(x):
print(x) # imprime pero NO devuelve
resultado = imprimir(5)
print(resultado) # → None ← error silencioso típico
# REGLA: si necesitas usar el resultado → usa return
# si solo necesitas que haga algo → no hace falta
# DEVOLVER MÚLTIPLES VALORES (tupla)
def min_max(lista):
return min(lista), max(lista)
minimo, maximo = min_max([3, 1, 4, 1, 5])
# FUNCIONES QUE LLAMAN A OTRAS
def es_aprobado(nota):
return nota >= 5
def clasificar(nota):
if nota >= 9: return "Sobresaliente"
elif nota >= 7: return "Notable"
elif es_aprobado(nota): return "Aprobado" # llama a otra función
else: return "Suspenso"
# ALCANCE — local vs global
x = 10 # global
def mi_funcion():
y = 20 # local — solo existe aquí
print(x) # puede leer globales
print(y)
mi_funcion()
print(x) # → 10 ✓
print(y) # → NameError ✗ — y no existe fuera
# CONSTANTES GLOBALES — en mayúsculas
IVA = 0.21
MAX_INTENTOS = 3
# PATRÓN: separar cálculo de presentación
def calcular(datos): # solo calcula, usa return
return resultado
def mostrar(resultado): # solo muestra, usa print
print(resultado)
def main(): # coordina todo
datos = input("...")
resultado = calcular(datos)
mostrar(resultado)
# ERRORES TÍPICOS
# 1. Olvidar return → función devuelve None
# 2. print en vez de return → valor no se puede usar
# 3. Llamar función antes de definirla → NameError
# 4. Variable local usada fuera → NameError
# 5. Modificar global desde función → bug difícil de encontrar
# DRY: Don't Repeat Yourself
# Si copias y pegas código → conviértelo en función

Un comentario