¿Cuáles son algunos usos comunes de los decoradores de Python? [cerrado]

Resuelto Dana asked hace 15 años • 0 respuestas

Si bien me gusta considerarme un codificador de Python razonablemente competente, un aspecto del lenguaje que nunca he podido asimilar son los decoradores.

Sé cuáles son (superficialmente), he leído tutoriales, ejemplos, preguntas sobre Stack Overflow y entiendo la sintaxis, puedo escribir la mía propia, ocasionalmente uso @classmethod y @staticmethod, pero nunca se me ocurre usar un decorador para resolver un problema en mi propio código Python. Nunca me encuentro con un problema en el que pienso: "Hmm... ¡esto parece un trabajo para un decorador!"

Entonces, me pregunto si podrían ofrecer algunos ejemplos de dónde han usado decoradores en sus propios programas y, con suerte, tendré un "¡Ajá!" momento y conseguirlos .

Dana avatar Jan 29 '09 05:01 Dana
Aceptado

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):
    ...
RSabet avatar Jan 29 '2009 01:01 RSabet

Los he usado para 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 puede usar una withdeclaración junto con un objeto threading.Lock(o multiprocessing.Lockdesde la versión 2.6) para simplificar la implementación del decorador a solo:

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

De todos modos, entonces lo usas así:

import threading
lock = threading.Lock()

@synchronized(lock)
def do_something():
  # etc

@synchronzied(lock)
def do_something_else():
  # etc

Básicamente simplemente coloca lock.acquire()/ lock.release()a cada lado de la llamada a la función.

John Fouhy avatar Jan 29 '2009 00:01 John Fouhy

Utilizo decoradores para los parámetros de verificación de tipos 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, se generan palabrerías una y otra vez.

Por ejemplo, en lugar de:

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

Sólo declaro:

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

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

Simon avatar Jan 28 '2009 23:01 Simon

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

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

Puede utilizar decoradores de clases 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 limpio para la decoración.

También hay una discusión sobre casos de uso en el grupo de noticias Python-Dev señalado por PEP 318 - Decoradores para funciones y métodos .

cdleary avatar Jan 28 '2009 22:01 cdleary

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

@parameters(
   (2, 4, 6),
   (5, 6, 11),
)
def test_add(a, b, expected):
    assert a + b == expected
Torsten Marek avatar Jan 29 '2009 00:01 Torsten Marek