建立裝飾器時保留元信息

當寫了一個裝飾器做用在某個函數上時,該函數的元信息就會丟失,好比名字,文檔,註解和參數簽名等。python

舉例:app

import time
def timer_func(func):
    '''
    用於對調用func函數時進行計時
    :param func: 函數對象做爲外函數的入參
    :return: 內函數
    '''
    def wrapper(*args,**kwargs):
        t1=time.time()
        r=func(*args,**kwargs)
        t2=time.time()
        cost=t2-t1
        print('time cost %s'%cost)
        return r
    return wrapper

@timer_func
def func(n:int):
    '''
    this is a func test
    :param n:
    :return:
    '''
    while n>0:
        n=n-1
    return n
>>>func(10000000)
time cost 0.6841702461242676
>>>print(func.__name__)
wrapper#名字時內函數的名字,再也不是函數自己的名字
>>>print(func.__annotations__)
{}#註解丟失
>>>print(func.__doc__)
None#文檔丟失

在這種狀況下,使用 functools 庫中的 @wraps 裝飾器來註解底層包裝函數能夠解決這個問題,好比:函數

def timer_func(func):
    '''
    用於對調用func函數時進行計時
    :param func: 函數對象做爲外函數的入參
    :return: 內函數
    '''
    @wraps(func)
    def wer(*args,**kwargs):
        t1=time.time()
        r=func(*args,**kwargs)
        t2=time.time()
        cost=t2-t1
        print('time cost %s'%cost)
        return r
    return wer

@timer_func
def func(n:int):
    '''
    this is a func test
    :param n:
    :return:
    '''
    while n>0:
        n=n-1
    return n
>>>func(10000000)
time cost 0.6841702461242676
>>>print(func.__name__)
func
>>>print(func.__annotations__)
{'n': <class 'int'>}
>>>print(func.__doc__)
    this is a func test
    :param n:
    :return:

所以,在使用裝飾器的場景中,都應該使用functools的wraps去裝飾內函數來保留元信息。this