Domina los decoradores en Python con un enfoque claro y práctico. Verás cómo proteger el acceso a funciones con una contraseña y cómo transformar resultados reutilizando lógica con un patrón profesional. La clave: entender el flujo con funciones anidadas, el uso de @ y el manejo de valores de retorno.
¿Cómo proteger una función con un decorador de contraseña?
Un decorador permite ejecutar lógica antes o después de una función. Aquí se usa para control de acceso con una constante de contraseña y el input del usuario.
¿Cuál es la estructura base del punto de entrada y la función?
- Definir el punto de entrada con
if __name__ == "__main__":.
- Declarar una función a proteger que imprime un mensaje.
- Usar una constante para la contraseña. En un entorno real se mencionó el hashing, pero aquí basta con una constante didáctica.
PASSWORD = "12345"
def needs_password():
print("La contraseña es correcta.")
def password_required(func):
def wrapper():
pwd = input("¿Cuál es tu contraseña? ")
if pwd == PASSWORD:
return func()
else:
print("La contraseña no es correcta.")
return wrapper
@password_required
def needs_password():
print("La contraseña es correcta.")
if __name__ == "__main__":
needs_password()
¿Qué conceptos clave aplicar aquí?
- Decorador: se declara con
@ sobre la función objetivo.
- Función anidada y scope:
wrapper vive dentro de password_required.
- Convención wrapper: la función interna suele llamarse así.
- Indentación: el
return wrapper pertenece a la función decoradora, no a wrapper.
- Control de acceso: si la contraseña falla, la función protegida no se ejecuta.
¿Qué cambia cuando la función decorada recibe parámetros?
Cuando la función tiene parámetros, el decorador usa args y kwargs para no atarse a una firma específica. Además, si transformas el resultado (por ejemplo, con upper), la función decorada debe devolver un valor.
¿Cómo aplicar args y kwargs en el wrapper?
*args: captura argumentos posicionales.
**kwargs: captura argumentos con nombre.
- La “expansión” con
* y ** pasa los argumentos originales a la función decorada.
def upper(func):
def wrapper(*args, **kwargs):
resultado = func(*args, **kwargs)
return resultado.upper()
return wrapper
¿Cómo se prepara la función decorada para ser transformada?
- Evitar
print dentro de la lógica principal.
- Usar
return para que el decorador reciba el valor y pueda modificarlo.
@upper
def say_my_name(nombre):
return f"Hola, {nombre}"
if __name__ == "__main__":
print(say_my_name("David")) # Hola, DAVID
¿Qué método de string se usa para la transformación?
- upper: método de string que convierte el texto a mayúsculas.
- Se aplica al resultado que regresa la función decorada.
¿Qué errores comunes y buenas prácticas resalta el instructor?
Comprender el flujo evita fallas típicas y hace más legible el código, una habilidad esencial cuando usas funciones de terceros la mayor parte del tiempo.
¿Por qué return importa más que print en decoradores?
- Si la función decorada hace
print y no return, su valor de retorno es None.
- Llamar
upper() sobre None produce un error: “'NoneType' object has no attribute 'upper'”.
- Solución: devolver el valor y dejar el
print en el punto de uso.
¿Cómo abordar mensajes de error y depuración?
- Leer el mensaje e inferir el objeto y el método en conflicto.
- Si el mensaje es críptico, buscar el texto del error en Google.
- Verificar valores de retorno y flujos condicionales.
¿Qué otras buenas prácticas se muestran?
- Usar constantes para configuraciones como contraseñas.
- Cuidar la indentación al retornar el
wrapper en el decorador.
- Entender el punto de entrada con
if __name__ == "__main__".
- Reutilizar lógica con decoradores para seguridad y transformación.
- Leer código como hábito: los decoradores aparecen en web, command line y data science.
Te leo en los comentarios: ¿qué patrón con decoradores usarás primero y qué caso práctico te gustaría automatizar con Python?