Al escribir código, a veces necesitará extender una función sin modificar su código directamente. En esta situación, los decoradores pueden ayudar.
Un decorador es un tipo especial de función que envuelve otra función. Le permiten agregar código adicional antes y después de la función original, lo que brinda una forma elegante de ampliar las funciones existentes.
¿Cómo trabajan los decoradores?
Las funciones de Python son ciudadanos de primera clase, lo que significa que puede asignarlas a variables, pasarlas como argumentos a otras funciones y devolverlas desde funciones. Estas propiedades facilitan la creación de decoradores.
Una función decoradora devuelve otra función. Actúa como un metafunción que agrega funcionalidad adicional a una función de destino. Cuando decoras una función, Python llama a la función decoradora y pasa la función objetivo como argumento.
La función de decorador puede realizar cualquier acción necesaria antes y después de llamar a la función de destino. También puede modificar el comportamiento de la función de destino devolviendo una nueva función o reemplazando la función original por completo.
Creación de una función de decorador
Para crear un decorador, defina una función que tome una función de destino como argumento y devuelva una función contenedora. La función contenedora contiene la funcionalidad adicional y una llamada a la función de destino.
Aquí, función_decorador acepta target_func como argumento. Vuelve wrapper_func que llama target_func ycontiene la funcionalidad adicional.
Decorar una función con el decorador
Para aplicar el decorador a una función de destino, utilice el @ sintaxis y coloque el decorador directamente encima de la definición de la función de destino.
Aquí el función_decorador decora mi_funcion. Por lo tanto, siempre que use mi_funcionPython llama función_decorador y pasa mi_funcion como argumento.
Tenga en cuenta que la función de decorador no utiliza paréntesis de apertura y cierre.
Para mayor claridad, el @ la sintaxis se parece más al azúcar sintáctico. Puede pasar la función objetivo directamente a la función decoradora como argumento:
func = decorator_func(my_function)
Manejo de argumentos de función dentro de decoradores
Para manejar argumentos de función dentro de decoradores, use *argumentos y **kwargs en la función contenedora. Estos permiten al decorador aceptar cualquier número de argumentos posicionales y de palabras clave.
El *argumentos y **kwargs dentro wrapper_func asegúrese de que el decorador pueda manejar cualquier argumento que pase a la función de destino.
Decoradores Con Argumentos
Los decoradores también pueden tomar sus propios argumentos. Esto le proporciona una forma más flexible de decorar funciones.
El mi_decorador La función toma un número (2) como argumento y devuelve un envoltura función. Esa función devuelve un interno función que llama a la función decorada ( saludar, en este caso) un determinado número de veces (2). De modo que:
Imprimirá "Hola, Príncipe" dos veces.
Usos prácticos de los decoradores
Puede usar decoradores para una amplia gama de propósitos, como registro, almacenamiento en caché, validación de entrada y optimización del rendimiento.
Decorador de troncos
Puede utilizar un decorador de registro para registrar información sobre la ejecución de una función. Esto puede ayudar a depurar o monitorear el comportamiento de funciones específicas.
import logging
logging.info("Entering function: %s", func.__name__)
result = func(*args, **kwargs)
logging.info("Exiting function: %s", func.__name__)
return result
return wrapper
Decorador de tiempos
Puede usar un decorador de tiempo para medir el tiempo de ejecución de la ejecución de una función. Es útil para perfilar u optimizar código.
import time
start_time = time.time()
result = target_func(*args, **kwargs)
end_time = time.time()
total = end_time - start_time
print(f"Function {target_func.__name__} took {total} seconds to run")
return result
return wrapper_func
Aplicar los decoradores:
Ahora verá la depuración cuando se ejecute la función y un resumen de cuánto tiempo lleva.
Autorización Decorador
Puede usar un decorador de autorizaciones para verificar si un usuario tiene los permisos necesarios para acceder a una función específica. La mayoría de los marcos web usan esta función para agregar una capa de seguridad. Un ejemplo común es el de Django. @Necesario iniciar sesión decorador.
if is_user_authorized():
result = target_func(*args, **kwargs)
return result
else:
raise PermissionError("Unauthorized access")
return wrapper_func
Estos ejemplos ilustran algunos casos de uso comunes para los decoradores. Puede crear decoradores para varios propósitos, según sus requisitos específicos.
Conceptos de decoradores avanzados
Los decoradores son fáciles de implementar y usar. Pero también son potentes y pueden proporcionar aún más flexibilidad y control.
Decoradores basados en clases
Además de los decoradores basados en funciones, Python también admite decoradores basados en clases.
Un decorador basado en clases es una clase que define un __llamar__ método mágico, lo que le permite utilizar la clase como decorador.
self.target_func = target_func
print("Calling function")
result = self.target_func(*args, **kwargs)
print("Function called")
return result
Este ejemplo define una clase de decorador. Cuando decoras una función con DecoradorClasePython invoca el __llamar__ método mágico, que aplica la funcionalidad del decorador a la función de destino.
Los decoradores basados en clases pueden mantener el estado en varias llamadas almacenando información en variables de instancia. Esto le permite implementaciones de decoradores más avanzadas y flexibles.
Decoradores de anidamiento y encadenamiento
Suponga que necesita combinar diferentes tipos de funcionalidad en una sola unidad para acciones relacionadas en una función. Puede lograr esto aplicando múltiples decoradores a una sola función.
Aquí, ambos decorador1 y decorador2 Decorar mi_funcion. siempre que uses mi_funcionla funcionalidad de decorador1 se aplica primero, luego el de decorador2.
Un ejemplo común es cuando necesita aplicar un solo publicación solicitud y Necesario iniciar sesión funcionalidad a una vista de Django.
Los beneficios de los decoradores
Los decoradores ofrecen varias ventajas que los hacen esenciales en muchos proyectos de Python:
- Reutilización de código: promueve la reutilización del código al separar las preocupaciones transversales de la lógica central.
- Principio SECO: se adhiere al principio Don't Repeat Yourself al aplicar la misma funcionalidad a múltiples funciones sin duplicación de código.
- Legibilidad y Mantenibilidad: mejora la legibilidad y el mantenimiento del código al mantener la funcionalidad principal enfocada y clara.
- Estilo pitónico: se alinea con el estilo Pythonic al enfatizar un código limpio, expresivo y legible.
Por estas razones, debe aprovechar los decoradores siempre que sea posible.
Prácticas recomendadas para el uso de decoradores
Cuando trabaje con decoradores, debe seguir ciertas prácticas recomendadas:
- Mantenga la funcionalidad del decorador enfocada en una preocupación específica, como el registro o el almacenamiento en caché. Esto promueve el código modular y hace que los decoradores sean más versátiles.
- Haga que los decoradores sean configurables usando parámetros y evitando valores codificados. Esto le permite personalizar el comportamiento del decorador al aplicarlo a diferentes funciones.
- Proporcione una descripción clara y concisa del propósito del decorador, sus parámetros (si los hay) y el comportamiento esperado cuando se aplica a una función.
- Si el decorador tiene algún efecto secundario, como modificar el comportamiento de la función o introducir dependencias adicionales, documente claramente estos efectos para referencia futura.
- Escriba pruebas unitarias para sus decoradores para asegurarse de que se comporten como usted espera. Pruebe diferentes escenarios y casos extremos para cubrir una amplia gama de situaciones.
Trabajar con funciones en Python
Los decoradores son una de las áreas centrales en las que sobresalen las funciones. En general, las funciones de Python son un bloque de construcción fundamental para organizar y reutilizar el código. Le permiten encapsular la funcionalidad, pasar datos y devolver resultados.
Comprender cómo definir y usar funciones es esencial para una programación efectiva en Python.
