¿Cuáles son algunos usos comunes de los decoradores de Python? [closed]
⏰ 7 minutos de lectura
Dana
Si bien me gusta considerarme un codificador de Python razonablemente competente, un aspecto del lenguaje que nunca he podido asimilar son los decoradores.
Sé lo que son (superficialmente), he leído tutoriales, ejemplos, preguntas sobre Stack Overflow y entiendo la sintaxis, puedo escribir la mía, ocasionalmente uso @classmethod y @staticmethod, pero nunca se me ocurre usar un decorador para resolver un problema en mi propio código de Python. Nunca me encuentro con un problema en el que pienso, “Hmm… ¡este parece un trabajo para un decorador!”
Entonces, me pregunto si ustedes podrían ofrecer algunos ejemplos de dónde han usado decoradores en sus propios programas, y espero tener un “¡Ajá!” momento y obtener a ellos.
Además, los decoradores son útiles para memorizar, es decir, almacenar en caché el resultado de una función que tarda en calcularse. El decorador puede devolver una función que verifica las entradas y, si ya se han presentado, devolver un resultado almacenado en caché.
– Pedro
25/10/2014 a las 21:37
Tenga en cuenta que Python tiene un decorador incorporado, functools.lru_cacheque hace exactamente lo que dijo Peter, desde Python 3.2, lanzado en febrero de 2011.
Utilizo decoradores principalmente para fines de sincronización.
def time_dec(func):
def wrapper(*arg):
t = time.clock()
res = func(*arg)
print func.func_name, time.clock()-t
return res
return wrapper
@time_dec
def myFunction(n):
...
Bajo Unix, time.clock() mide el tiempo de CPU. Es posible que desee utilizar time.time() en cambio, si desea medir el tiempo del reloj de pared.
– Jabba
4 de febrero de 2013 a las 17:45
¡Gran ejemplo! Sin embargo, no tengo idea de lo que hace. Sería muy bueno una explicación de lo que está haciendo allí y cómo el decorador resuelve el problema.
– MeLuz
15/06/2014 a las 16:00
Bueno, mide el tiempo que tarda en myFunction correr …
– RSabet
14 de junio de 2015 a las 22:12
@time_dec es azúcar sintático para: myFunction = time_dec(myFunction). El resto es Python estándar.
Como se señaló en los comentarios, desde Python 2.5 puedes usar un with declaración junto con una threading.Lock (o multiprocessing.Lock desde la versión 2.6) para simplificar la implementación del decorador a solo:
Básicamente solo pone lock.acquire() / lock.release() a ambos lados de la llamada de función.
Posiblemente justificado, pero los decoradores son inherentemente confusos, especialmente. a los novatos de primer año que vienen detrás de ti e intentan modificar tu código. Evite esto con sencillez: simplemente haga que do_something() encierre su código en un bloque bajo ‘with lock:’ y todos podrán ver claramente su propósito. Los decoradores son utilizados en exceso por personas que quieren parecer inteligentes (y muchos lo son), pero luego el código llega a los simples mortales y se enfada.
– Kevin J. Arroz
25/11/2014 a las 16:40
@ KevinJ.Rice Restringir su código para que los ‘novatos de primer año’ puedan entenderlo mejor es una práctica terrible. La sintaxis de Decorator es mucho más fácil de leer y desacopla en gran medida el código.
– Taylor Jones
04/02/2015 a las 20:02
@TaylerJones, la legibilidad del código es casi mi máxima prioridad al escribir. El código se lee más de 7 veces por cada vez que se modifica. El código difícil de entender (para novatos o expertos que trabajan bajo presión de tiempo) es una deuda técnica que debe pagarse cada vez que alguien visita el árbol de código fuente.
– Kevin J. Arroz
5 de febrero de 2015 a las 20:28
@TaylerJones Una de las tareas más importantes para un programador es brindar claridad.
– JDOaktown
23 de junio de 2019 a las 20:15
@JDOaktown, una tarea importante para los programadores es poder comprender conceptos simples de los lenguajes con los que trabajan.
– DMeneses
16 abr 2021 a las 23:36
Simón
Utilizo decoradores para los parámetros de verificación de tipo que se pasan a mis métodos de Python a través de algún RMI. Entonces, en lugar de repetir el mismo conteo de parámetros, genera excepciones una y otra vez.
Por ejemplo, en lugar de:
def myMethod(ID, name):
if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
raise BlaBlaException() ...
Para cualquier persona interesada, hay una implementación de @accepts en PEP 318.
– martineau
15 de septiembre de 2010 a las 11:23
Creo que hay un error tipográfico… el primer método debería aceptarse… declaraste ambos como “myMethod”
– Desarrollador
29 de abril de 2014 a las 13:05
@DevC No, no parece un error tipográfico. Dado que claramente no es una implementación de “acepta (…)”, y aquí “acepta (…)” hace el trabajo que de otro modo harían las dos líneas al comienzo de “myMethod (…)” — ese es el única interpretación que encaja.
–Evgeni Sergeev
24 de octubre de 2015 a las 12:23
Perdón por el golpe, solo quería señalar que verificar el tipo de argumentos pasados y generar un TypeError de lo contrario se considera una mala práctica porque no aceptará, por ejemplo, un int si solo verifica los flotantes, y porque normalmente el el propio código debe adaptarse a diferentes tipos de valores pasados para una máxima flexibilidad.
– Gustavo6046
16/04/2016 a las 21:16
La forma recomendada de realizar la verificación de tipos en Python es a través de la isinstance() función, como se hace en el PEP 318 implementación del decorador. Desde su classinfo El argumento puede ser de uno o más tipos, usarlo también mitigaría las objeciones (válidas) de @ Gustavo6046. Python también tiene un Number clase base abstracta, pruebas muy genéricas como isinstance(42, numbers.Number)es posible.
– martineau
27 de noviembre de 2019 a las 0:13
diario
Los decoradores se utilizan para cualquier cosa que desee “envolver” de forma transparente con funcionalidad adicional.
Puede usar decoradores de clase para agregar registros con nombre a las clases.
Cualquier funcionalidad suficientemente genérica que pueda “añadir” al comportamiento de una clase o función existente es un juego justo para la decoración.
Usando esto, el código que se habría dividido en un montón de pequeñas funciones de devolución de llamada se puede escribir de forma bastante natural como un solo bloque, lo que lo hace mucho más fácil de entender y mantener.
Un uso obvio es para iniciar sesión, por supuesto:
import functools
def log(logger, level="info"):
def log_decorator(fn):
@functools.wraps(fn)
def wrapper(*a, **kwa):
getattr(logger, level)(fn.__name__)
return fn(*a, **kwa)
return wrapper
return log_decorator
# later that day ...
@log(logging.getLogger('main'), level="warning")
def potentially_dangerous_function(times):
for _ in xrange(times): rockets.get_rocket(NUCLEAR=True).fire()
¿Ha sido útil esta solución?
Tu feedback nos ayuda a saber si la solución es correcta y está funcionando. De esta manera podemos revisar y corregir el contenido.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
Además, los decoradores son útiles para memorizar, es decir, almacenar en caché el resultado de una función que tarda en calcularse. El decorador puede devolver una función que verifica las entradas y, si ya se han presentado, devolver un resultado almacenado en caché.
– Pedro
25/10/2014 a las 21:37
Tenga en cuenta que Python tiene un decorador incorporado,
functools.lru_cache
que hace exactamente lo que dijo Peter, desde Python 3.2, lanzado en febrero de 2011.– Ignacio
30 de julio de 2019 a las 4:30
Los Contenidos de la Biblioteca de decoradores de Python debería darle una buena idea de otros usos para ellos.
– martineau
27 de noviembre de 2019 a las 0:21