‘@’引用已有的函數,對下面的函數進行修飾。引用函數必須放在修飾函數的上面,引用函數的返回值,返回給被修飾的函數
一個簡單的栗子:
1 def funA(fn): 2 print('A') # 輸出A 3 fn() # 執行傳入的fn參數 輸出B 4 return 'fkit' # 返回給funB 5 ''' 6 下面裝飾效果相當於:funA(funB), 7 funB將會替換(裝飾)成該語句的返回值; 8 由於funA()函數返回fkit,因此funB就是fkit 9 ''' 10 @funA 11 def funB(): 12 print('B') 13 print(funB) # 此時再運行funB函數輸出的是fkit
這里funA是引用的函數,funB是被修飾的函數。@修飾符的功能就是把funB當做參數傳遞給funA,然后把funA的返回值返回到funB
這意味着程序要完成兩步操作:
將 funB 作為 funA() 的參數,也就是上面代碼中 @funA 相當於執行 funA(funB)。
將 funB 替換成上一步執行的結果,funA() 執行完成后返回 fkit,因此 funB 就不再是函數,而是被替換成一個字符串。
輸出如下:
A
B
Fkit
當然,也可以返回一個函數,看下面這個栗子:
1 def my_decorator(func): 2 def wrapper(): # 暫時跳過這個函數 3 '''decorator''' 4 print('Decorated function...') 5 print('123') 6 return wrapper # 把wrapper函數返回給test 7 8 9 @my_decorator # decorator(test()) 10 def test(): 11 """Testword""" 12 print('Test function') 13 14 15 test() 16 print("函數名:%s" % test.__name__)
輸出如下:
123
Decorated function...
函數名:wrapper
可以看出,最先輸出了第五行的‘123’,然后是第四行的‘Decorated function...’,最后是第十六行的函數名,下面捋一下代碼的執行順序:
最先執行了第9行代碼,開始運行被引用函數,被引用函數的返回值是里面的嵌套函數wrapper,暫時跳過這個嵌套函數,運行到第5行,此時輸出‘123’;運行第六行把內嵌函數返回給test函數,此時@修飾符的作用就算是已經完成了,接下來,代碼運行第15行,調用test函數,但此時並沒有test里面的
'Test function',二是輸出了wrapper里面的'Decorated function...',這就是把函數作為被引用函數返回值的效果,此時的test本質上已經不再是test了,二是被引用函數的返回值wrapper函數,所以輸出內容是wrapper函數里面的,最后,我們輸出函數名驗證一下。
這就是@修飾符的作用了,還不會飛的小菜雞,文章有錯誤歡迎大佬隨時指正。
-----------------------------------------努力,不只是一種習慣,更是一種品質。