Compra libros de Python en Amazon al mejor precio
Ejercicio 1: Medir el Tiempo de Ejecución
medir_tiempo
time.sleep()
Ejercicio 2: Registrar Llamadas a Función
registrar_llamada
Ejercicio 3: Validar Argumentos
validar_argumento
int
str
TypeError
Ejercicio 4: Memorización (Caching Simple)
memoizar
Ejercicio 5: Retry con Límite
intentar_de_nuevo
Mostrar/Ocultar ejercicios resueltos
Solución al Ejercicio 1: Medir el Tiempo de Ejecución
import time def medir_tiempo(func): def wrapper(*args, **kwargs): inicio = time.time() resultado = func(*args, **kwargs) fin = time.time() print(f"La función '{func.__name__}' tardó {fin - inicio:.4f} segundos en ejecutarse.") return resultado return wrapper @medir_tiempo def tarea_larga(): time.sleep(2) print("Tarea larga completada.") @medir_tiempo def calcular_suma(n): suma = 0 for i in range(n): suma += i return suma tarea_larga() resultado_suma = calcular_suma(1000000) print(f"Resultado de la suma: {resultado_suma}")
Solución al Ejercicio 2: Registrar Llamadas a Función
def registrar_llamada(func): def wrapper(*args, **kwargs): print(f"Llamando a la función: '{func.__name__}' con argumentos: {args}, {kwargs}") return func(*args, **kwargs) return wrapper @registrar_llamada def saludar(nombre): return f"Hola, {nombre}!" @registrar_llamada def sumar(a, b): return a + b saludo = saludar("Mundo") resultado_suma = sumar(5, 3) print(saludo) print(resultado_suma)
Solución al Ejercicio 3: Validar Argumentos
def validar_argumento(tipo_esperado): def decorador(func): def wrapper(*args, **kwargs): for arg in args: if not isinstance(arg, tipo_esperado): raise TypeError(f"El argumento debe ser de tipo {tipo_esperado}, pero se recibió {type(arg)}") for kwarg in kwargs.values(): if not isinstance(kwarg, tipo_esperado): raise TypeError(f"El argumento '{kwarg}' debe ser de tipo {tipo_esperado}, pero se recibió {type(kwarg)}") return func(*args, **kwargs) return wrapper return decorador @validar_argumento(int) def multiplicar_por_dos(numero): return numero * 2 @validar_argumento(str) def concatenar(texto1, texto2=""): return texto1 + texto2 resultado_multiplicacion = multiplicar_por_dos(5) print(resultado_multiplicacion) try: multiplicar_por_dos("hola") except TypeError as e: print(f"Error: {e}") resultado_concatenacion = concatenar("Hola", " Mundo") print(resultado_concatenacion) try: concatenar(123) except TypeError as e: print(f"Error: {e}")
Solución al Ejercicio 4: Memorización (Caching Simple)
def memoizar(func): cache = {} def wrapper(*args): if args not in cache: cache[args] = func(*args) return cache[args] return wrapper @memoizar def fibonacci(n): if n <= 1: return n return fibonacci(n - 1) + fibonacci(n - 2) print(fibonacci(10)) print(fibonacci(10)) # El resultado se obtiene del caché print(fibonacci(20))
Solución al Ejercicio 5: Retry con Límite
import time import random def intentar_de_nuevo(max_intentos): def decorador(func): def wrapper(*args, **kwargs): intentos = 0 while intentos < max_intentos: try: return func(*args, **kwargs) except Exception as e: intentos += 1 print(f"Error al llamar a '{func.__name__}': {e}, intentando de nuevo ({intentos}/{max_intentos})...") time.sleep(random.uniform(0.1, 0.5)) # Espera un poco antes de reintentar raise Exception(f"Falló después de {max_intentos} intentos.") return wrapper return decorador @intentar_de_nuevo(3) def operacion_fallida_aleatoriamente(): if random.random() < 0.7: raise IOError("¡La operación falló!") return "Operación exitosa." try: resultado = operacion_fallida_aleatoriamente() print(f"Resultado: {resultado}") except Exception as e: print(f"Error final: {e}")