qué puede parametros ejemplo depurar decoradores decorador cómo código con python decorator

puede - qué es un decorador en python



¿Cuáles son algunos usos comunes para los decoradores de Python? (13)

Decorador se puede utilizar para crear fácilmente variables de método de función.

def static_var(varname, value): '''''' Decorator to create a static variable for the specified function @param varname: static variable name @param value: initial value for the variable '''''' def decorate(func): setattr(func, varname, value) return func return decorate @static_var("count", 0) def mainCallCount(): mainCallCount.count += 1

Aunque me gusta considerarme un codificador de Python razonablemente competente, un aspecto del lenguaje que nunca he podido asimilar es a los decoradores.

Sé lo que son (superficialmente), he leído tutoriales, ejemplos, preguntas sobre el desbordamiento de pila, y entiendo la sintaxis, puedo escribir la mía, usar ocasionalmente @classmethod y @staticmethod, pero nunca se me ocurre usar un Decorador para resolver un problema en mi propio código Python. Nunca encuentro un problema donde pienso, "Hmm ... ¡esto parece ser 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 que tengan un "¡A-ha!" momento y conseguirlos .


Estoy usando el siguiente decorador para hacer una función segura para hilos. Hace que el código sea más legible. Es casi similar al propuesto por John Fouhy, pero la diferencia es que uno funciona en una sola función y que no hay necesidad de crear un objeto de bloqueo explícitamente.

def threadsafe_function(fn): """decorator making sure that the decorated function is thread safe""" lock = threading.Lock() def new(*args, **kwargs): lock.acquire() try: r = fn(*args, **kwargs) except Exception as e: raise e finally: lock.release() return r return new class X: var = 0 @threadsafe_function def inc_var(self): X.var += 1 return X.var


La biblioteca Twisted utiliza decoradores combinados con generadores para dar la ilusión de que una función asíncrona es síncrona. Por ejemplo:

@inlineCallbacks def asyncf(): doStuff() yield someAsynchronousCall() doStuff() yield someAsynchronousCall() doStuff()

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 hace que sea mucho más fácil de entender y mantener.


Los decoradores se utilizan para cualquier cosa que desee "envolver" de forma transparente con funcionalidad adicional.

Django los usa para envolver la funcionalidad de "inicio de sesión requerido" en las funciones de visualización , así como para registrar funciones de filtro .

Puede utilizar decoradores de clase para agregar registros con nombre a las clases .

Cualquier funcionalidad suficientemente genérica que pueda "agregar" al comportamiento de una clase o función existente es un juego justo para la decoración.

También hay una discusión de casos de uso en el grupo de noticias Python-Dev señalado por PEP 318 - Decorators for Functions and Methods .


Los decoradores se utilizan para definir las propiedades de una función o como repetitivo que lo altera; Es posible, pero contrario a la intuición, que devuelvan funciones completamente diferentes. Mirando las otras respuestas aquí, parece que uno de los usos más comunes es limitar el alcance de algún otro proceso, ya sea el registro, la creación de perfiles, las verificaciones de seguridad, etc.

CherryPy utiliza el envío de objetos para hacer coincidir las URL con los objetos y, eventualmente, con los métodos. Los decoradores de esos métodos señalan si CherryPy puede usar esos métodos. Por ejemplo, adaptado del tutorial :

class HelloWorld: ... def secret(self): return "You shouldn''t be here." @cherrypy.expose def index(self): return "Hello world!" cherrypy.quickstart(HelloWorld())


Los he usado para la sincronización.

import functools def synchronized(lock): """ Synchronization decorator """ def wrap(f): @functools.wraps(f) def newFunction(*args, **kw): lock.acquire() try: return f(*args, **kw) finally: lock.release() return newFunction return wrap

Como se señaló en los comentarios, desde Python 2.5 se puede usar una instrucción with junto con un objeto threading.Lock (o multiprocessing.Lock since versión 2.6) para simplificar la implementación del decorador para:

import functools def synchronized(lock): """ Synchronization decorator """ def wrap(f): @functools.wraps(f) def newFunction(*args, **kw): with lock: return f(*args, **kw) return newFunction return wrap

Independientemente, entonces lo usas así:

import threading lock = threading.Lock() @synchronized(lock) def do_something(): # etc @synchronzied(lock) def do_something_else(): # etc

Básicamente, solo pone lock.acquire() / lock.release() a ambos lados de la llamada a la función.


Los usé recientemente, mientras trabajaba en la aplicación web de redes sociales. Para la Comunidad / Grupos, se suponía que debía otorgar la autorización de membresía para crear una nueva discusión y responder a un mensaje que debe ser el miembro de ese grupo en particular. Por lo tanto, escribí un decorador @membership_required y puse eso donde lo necesitaba en mi opinión.


Los uso principalmente para la depuración (ajuste alrededor de una función que imprime sus argumentos y resultados) y verificación (por ejemplo, para verificar si un argumento es del tipo correcto o, en el caso de una aplicación web, si el usuario tiene privilegios suficientes para llamar a un determinado método).


Para las pruebas de detección, puede escribir un decorador que proporcione una función de prueba de unidad o un método con varios conjuntos de parámetros:

@parameters( (2, 4, 6), (5, 6, 11), ) def test_add(a, b, expected): assert a + b == expected


Un uso obvio es para el registro, 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()


Uso decoradores para los parámetros de verificación de tipos que se pasan a mis métodos de Python a través de algunos RMI. Así que en lugar de repetir el mismo parámetro contando, mumbo-jumbo aumenta las excepciones una y otra vez

def myMethod(ID, name): if not (myIsType(ID, ''uint'') and myIsType(name, ''utf8string'')): raise BlaBlaException() ...

Acabo de declarar

@accepts(uint, utf8string) def myMethod(ID, name): ...

y acepta () hace todo el trabajo por mí.


Uso este decorador para arreglar el parámetro.

def fill_it(arg): if isinstance(arg, int): return "wan" + str(arg) else: try: # number present as string if str(int(arg)) == arg: return "wan" + arg else: # This should never happened raise Exception("I dont know this " + arg) print "What arg?" except ValueError, e: return arg def fill_wanname(func): def wrapper(arg): filled = fill_it(arg) return func(filled) return wrapper @fill_wanname def get_iface_of(wanname): global __iface_config__ return __iface_config__[wanname][''iface'']

esto escrito cuando refactorizo ​​algunas funciones debo pasar el argumento "wanN" pero en mis códigos anteriores, pasé N o ''N'' solamente


Yo uso decoradores principalmente para fines de tiempo

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): ...