python 中decorator的做用就是一個包裝的做用,所謂包裝指在執行真正的函數以前或者以後,咱們能夠有一些額外的發揮餘地。python
decorator形式以下web
def dec(arg1): print("dec",arg1) def func_replace(func): print("func_replace",func) def call_real_func(*args,**kwargs): print("call_real_func") func(*args,**kwargs) return call_real_func return func_replace @dec("abc") def realfun(arg): print("realfun",arg) realfun("123")
"@"的做用,咱們經過這份代碼產生的python bytecode來弄清楚@的做用函數
F:\pyweb>python -m dis decorator.py
源碼行號 字節碼偏移 字節碼 註釋
1 0 LOAD_CONST 0 (<code object dec at 00BE74A0, file "decorator.py", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (dec)
//到此爲止是def dec(): 產生 表明dec PyFunction的字節碼code
12 9 LOAD_NAME 0 (dec) //加載 dec 對應的PyFunctionObject
12 LOAD_CONST 1 ('abc') //壓入 'abc'到value-stack
15 CALL_FUNCTION 1 //調用函數,就是dec('abc'),而後建dec 返回的 func_replace壓到 value stack
//到此至關於 dec('abc')
18 LOAD_CONST 2 (<code object realfun at 00BE74E8, file "decorator.py", line 12>) blog
//將表明realfun的PyCodeObject壓入value stack
21 MAKE_FUNCTION 0
//根據棧頂表明realfun的PyCodeObject生成 PyFunctionObject,返回以後,源碼
//value stack的值爲:PyFunctionObject(func_replace),PyFunctionObject(realfun)
24 CALL_FUNCTION 1 io
//調用func_replace(realfun) ,返回call_real_func 這個PyFunctionObject壓入class
//value stack
//到此至關於 dec('abc')(realfun)
27 STORE_NAME 1 (realfun) //替換掉 realfun
//到此至關於realfun=dec('abc')(realfun)object
17 30 LOAD_NAME 1 (realfun)
33 LOAD_CONST 3 ('123')
36 CALL_FUNCTION 1
39 POP_TOP
40 LOAD_CONST 4 (None)
43 RETURN_VALUEfile
分析以後能夠知道@的做用就是在調用dec以後又添加了一個調用,並且這個調用的格式是固定的是func( realfun)這種。
因此
@dec("abc")
def realfun(arg):
print("realfun",arg)
這個的實際做用是realfun=dec('abc')(realfun)。中間有一個產生PyFunctionObject,而且隱藏了調用dec返回PyFunctionObject的過程
另外有一種沒有參數的decorator,他們省去了調用dec這一步,效果至關於realfun=dec(realfun);