¿Cómo conservar los metadatos de funciones al usar decoradores?

Los decoradores son una herramienta muy poderosa y útil en Python, ya que permite a los programadores modificar el comportamiento de una función o clase. Los decoradores nos permiten envolver otra función para extender el comportamiento de la función envuelta, sin modificarla permanentemente.
Nota: Para obtener más información, consulte Decoradores en Python
 

¿Cómo preservar los metadatos?

Esto se puede hacer usando el método wraps() de las funciones. Actualiza la función contenedora para que parezca una función envuelta copiando atributos como __name__, __doc__ (la string de documentación), etc. 
Ejemplo:

Python3

import time
from functools import wraps
 
 
def timethis(func):
    '''Decorator that reports the execution time.'''
     
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
         
        print(func.__name__, end-start)
        return result
     
    return wrapper
 
@timethis
def countdown(n:int):
    '''Counts down'''
    while n > 0:
        n -= 1
         
countdown(100000)
print(countdown.__name__)
print(countdown.__doc__)
print(countdown.__annotations__)

Producción: 

countdown 0.00827932357788086
countdown
Counts down
{'n': <class 'int'>}

Ventajas de usar wraps(): 

  • La copia de metadatos de decoradores es una parte importante de la escritura de decoradores. Si olvida usar @wraps , encontrará que la función decorada pierde todo tipo de información útil. Por ejemplo, si se omite, la salida del último ejemplo se vería así:
countdown 0.030733823776245117
wrapper
None
{}
  • Una característica importante del decorador @wraps es que hace que la función envuelta esté disponible en el atributo __envuelto__ . Por ejemplo, si desea acceder directamente a la función envuelta, puede hacer esto:
countdown.__wrapped__(100000)
  • La presencia del atributo __wrapped__ también hace que las funciones decoradas expongan correctamente la firma subyacente de la función envuelta. Por ejemplo: 

Python3

from inspect import signature
 
 
print(signature(countdown))
  • Producción:
(n:int)

Publicación traducida automáticamente

Artículo escrito por yuvrajeyes y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *