Skip to content
Related Articles

Related Articles

How to preserve Function Metadata while using Decorators?
  • Last Updated : 22 Jun, 2020

Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behavior of function or class. Decorators allow us to wrap another function in order to extend the behavior of the wrapped function, without permanently modifying it.

Note: For more information, refer Decorators in Python

How to preserve Metadata?

This can be done using the wraps() method of the functools. It updates the wrapper function to look like wrapped function by coping attributes such as __name__, __doc__ (the docstring), etc.

Example:

filter_none

edit
close

play_arrow

link
brightness_4
code

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__)

chevron_right


Output:



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

Advantanges of using wraps():

  • Copying decorator metadata is an important part of writing decorators. If you forget to use @wraps, you’ll find that the decorated function loses all sorts of useful information. For example, if omitted, the output of the last example would look like this:
    countdown 0.030733823776245117
    wrapper
    None
    {}
  • An important feature of the @wraps decorator is that it makes the wrapped function available to you in the __wrapped__ attribute. For example, if you want to access the wrapped function directly, you could do this:
    countdown.__wrapped__(100000)
  • The presence of the __wrapped__ attribute also makes decorated functions properly expose the underlying signature of the wrapped function. For example:
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    from inspect import signature
      
      
    print(signature(countdown))

    chevron_right

    
    

    Output:

    (n:int)

Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course.

My Personal Notes arrow_drop_up
Recommended Articles
Page :