個人關於python裝飾器的白痴理解


無參數裝飾器

對於python小白來說,python的裝飾器簡直讓人懵逼,不知如何理解,其實按照裝飾器的字面意思,

就是把自己定義的函數裝飾一遍,然后返回一個新的函數(注意是新的,已經不是本來定義的函數了)

為什么這么說,我用一個裝飾器最原始的例子來說明,看一下代碼:

 1 #裝飾函數
 2 def decorator(foo):
 3     def wrapper():
 4         print 'wrapper'
 5         return foo()
 6     return wrapper
 7 
 8 #自定義函數
 9 def abc():
10     print 'abc'
11 
12 #裝飾abc
13 abc = decorator(abc)

以上就是裝飾器的過程,可以看出調用decorator函數,返回的是wrapper函數對象,而不是abc這個函數對象,

abc這個函數在wrapper中已經是被調用了的,只是返回一個結果。以上代碼的運行結果如下圖,可以看出裝飾

之后的abc是wrapper的函數對象,而不是原來函數了。

而python的語法糖'@'就是執行了以上的過程,下面的代碼和上面的代碼原理是一樣的:

1 def decorator(foo):
2     def wrapper():
3         print 'wrapper'
4         return foo()
5     return wrapper
6 
7 @decorator
8 def abc():
9     print 'abc'

python的裝飾器語法就是自動調用decorator函數,並以自定義的函數abc函數對象為參數,

返回wrapper函數對象,這樣一個過程。

帶參數的裝飾器:

接下來,再深一步來說說帶參數的裝飾器, 其實這個只比上面那個無參數裝飾器多了一步,

就是先調用裝飾器函數,再返回真正的裝飾器,之后的步驟和無參數的一樣了,說得太抽象?

直接上代碼,這樣就明顯了,先調用用最外層的函數,返回的是一個真正的裝飾器,然后像

之前無參數的時候一樣,修飾abc函數后返回新的函數對象。

 1 def decoratorFunc(arg):
 2     def decorator(foo):
 3         def wrapper():
 4             if arg == 0:
 5                 print 'lalala'
 6             return foo()
 7         return wrapper
 8     return decorator
 9 
10 deco0 = decoratorFunc(0)
11 deco1 = decoratorFunc(1)
12 
13 abc0 = deco0(abc)
14 abc1 = deco1(abc)

然后python的語法糖的過程也是像上面那樣了,所以我得出一個結論,就是@后面一定是一個

函數對象,而非函數調用!

1 @decoratorFunc(0)
2 def abc():
3     print 'abc'

最后

寫更普通的裝飾器,如果被裝飾的函數有參數怎么辦?很簡單,利用python的可變長度參數就行。

注意,是在wrapper這個函數上我們寫上python的可變長度參數,而裝飾器函數decorator的參數

永遠只有一個,就是函數對象。看以下代碼,是無參數裝飾器的例子,如果是帶參數的函數,也只

需要把wrapper改成接收可變長度參數就行。

 1 def decorator(foo):
 2     def wrapper(*args, **kwargs):
 3         print 'wrapper'
 4         return foo(*args, **kwargs)
 5     retrun wrapper
 6 
 7 
 8 @decorator
 9 def abc(arg):
10     print 'abc:', arg

 


 

作者:陳棟權

時間:2016/09/05

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,

且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

如有特別用途,請與我聯系郵箱:kingchen.gd@foxmail.com

 

最后有興趣的同學可以關注我的微信公眾號,可以隨時及時方便看我的文章。*^_^*

掃碼關注或者搜索微信號:King_diary 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM