裝飾器裝飾過(guò)函數(shù)func, 此時(shí)func不是指向真正的func,而是指向裝飾器中的裝飾過(guò)的函數(shù)
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 其實(shí)指向的是 calls, 可以用help(square)或者 square.__name__ 看下。
square 被裝飾后的函數(shù)其實(shí)已經(jīng)是另外一個(gè)函數(shù)了(函數(shù)名等函數(shù)屬性會(huì)發(fā)生改變)
如果使用wraps進(jìn)行修飾
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
此時(shí) 用trace 裝飾的 square 的屬性就不會(huì)變化了,可以help(square) 看看
原因:我們把wraps的裝飾的代碼翻譯如下,其等價(jià)為:
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做的工作很簡(jiǎn)單,就是用參數(shù)wrapped表示的函數(shù)對(duì)象(例如:square)的一些屬性(如:__name__、 __doc__)覆蓋參數(shù)wrapper表示的函數(shù)對(duì)象(例如:callf,這里callf只是簡(jiǎn)單地調(diào)用square函數(shù),因此可以說(shuō)callf是 square的一個(gè)wrapper function)的這些相應(yīng)屬性。
因此,本例中使用wraps裝飾器“裝飾”過(guò)callf后,callf的__doc__、__name__等屬性和trace要“裝飾”的函數(shù)square的這些屬性完全一樣。
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com