裝飾器裝飾過函數func, 此時func不是指向真正的func,而是指向裝飾器中的裝飾過的函數
import sys debug_log = sys.stderr def trace(func): if debug_log: def callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {} '.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {} '.format(res)) return res return callf else: return func @trace def square(x): """Calculate the square of the given number.""" return x * x
這里的 square 其實指向的是 calls, 可以用help(square)或者 square.__name__ 看下。
square 被裝飾后的函數其實已經是另外一個函數了(函數名等函數屬性會發生改變)
如果使用wraps進行修飾
def trace(func): if debug_log: @functools.wraps(func) def callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {} '.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {} '.format(res)) return res return callf else: return func
此時 用trace 裝飾的 square 的屬性就不會變化了,可以help(square) 看看
原因:我們把wraps的裝飾的代碼翻譯如下,其等價為:
def trace(func): if debug_log: def _callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {} '.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {} '.format(res)) return res callf = functools.update_wrapper(_callf, wrapped = func,assigned = functools.WRAPPER_ASSIGNMENTS,updated = functools.WRAPPER_UPDATES) return callf else: return func
update_wrapper做的工作很簡單,就是用參數wrapped表示的函數對象(例如:square)的一些屬性(如:__name__、 __doc__)覆蓋參數wrapper表示的函數對象(例如:callf,這里callf只是簡單地調用square函數,因此可以說callf是 square的一個wrapper function)的這些相應屬性。
因此,本例中使用wraps裝飾器“裝飾”過callf后,callf的__doc__、__name__等屬性和trace要“裝飾”的函數square的這些屬性完全一樣。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com