課程
/后端開發
/Python
/python進階
裝飾器不是這樣起作用的嗎:f = log(f),為什么函數名還會被修改?
2015-10-25
源自:python進階 2-14
正在回答
我自己的理解:
1.以上面的log函數為例,log內部定義了fn函數,fn.__name__ 為 'fn'
def?log(f): ????def?fn(x): ????????print?'call?'?+?f.__name__?+?'()...' ????????return?f(x) ????return?fn
當執行了f = log(f),因為log函數返回的也是一個函數(fn),所以f實際指向的函數(fn),f.__name__ 為 'fn'
你可以試下: f=log,此時,f指向的函數就是(log),f.__name__ 為 'log'
2.再進一步,以本題答案為例:
def?performance(unit): ????def?perf_decorator(f): [email protected](f) ????????def?wrapper(*args,?**kw): ????????????t1?=?time.time() ????????????r?=?f(*args,?**kw) ????????????t2?=?time.time() ????????????t?=?(t2-t1)*1000?if?unit?==?'ms'?else?t2-t1 ????????????print?'call?%s()?in?%f?%s'%(f.__name__,t,unit) ????????????return?r ????????return?wrapper ????return?perf_decorator
本質是 f =?performance(unit)(f)
performance(unit) 返回 perf_decorator 函數,perf_decorator(f) 返回 wrapper函數,所以f指向wrapper函數,如果不加裝飾器@functools.wraps(f),則f.__name__ 為 'wrapper'。
加了@functools.wraps(f)之后,functools.wraps函數會執行 wrapper.__name__ ?= f.__name__?
所以最終f.__name__ 的值仍為'f',有點繞,這是我自己的理解。
3.你可以在編寫帶參數的那章執行如下代碼看看:
#?-*-?coding:?utf-8?-*- import?time def?performance(unit): ????def?perf_decorator(f): ????????def?wrapper(*args,?**kw): ????????????t1?=?time.time() ????????????r?=?f(*args,?**kw) ????????????t2?=?time.time() ????????????t?=?(t2-t1)*1000?if?unit?==?'ms'?else?t2-t1 ????????????print?'call?%s()?in?%f?%s'%(f.__name__,t,unit) ????????????return?r ????????return?wrapper ????return?perf_decorator #@performance('ms')?不用裝飾器 def?factorial(n): ????return?reduce(lambda?x,y:?x*y,?range(1,?n+1)) #手動裝飾 factorial?=?performance('ms')(factorial) print?factorial(10) print?factorial.__name__
啊啊啊
舉報
學習函數式、模塊和面向對象編程,掌握Python高級程序設計
Copyright ? 2025 imooc.com All Rights Reserved | 京ICP備12003892號-11 京公網安備11010802030151號
購課補貼聯系客服咨詢優惠詳情
慕課網APP您的移動學習伙伴
掃描二維碼關注慕課網微信公眾號
2016-01-27
我自己的理解:
1.以上面的log函數為例,log內部定義了fn函數,fn.__name__ 為 'fn'
當執行了f = log(f),因為log函數返回的也是一個函數(fn),所以f實際指向的函數(fn),f.__name__ 為 'fn'
你可以試下: f=log,此時,f指向的函數就是(log),f.__name__ 為 'log'
2.再進一步,以本題答案為例:
本質是 f =?performance(unit)(f)
performance(unit) 返回 perf_decorator 函數,perf_decorator(f) 返回 wrapper函數,所以f指向wrapper函數,如果不加裝飾器@functools.wraps(f),則f.__name__ 為 'wrapper'。
加了@functools.wraps(f)之后,functools.wraps函數會執行 wrapper.__name__ ?= f.__name__?
所以最終f.__name__ 的值仍為'f',有點繞,這是我自己的理解。
3.你可以在編寫帶參數的那章執行如下代碼看看:
2015-12-14
啊啊啊