1. 程式人生 > >Python裝飾器的本質理解

Python裝飾器的本質理解

我又回來了,深夜更文,神情倉促。。。最近在華為做openstack相關的一些專案,順便進修了一下Python知識,看到裝飾器這一塊時懵懂極了,網上找的大概都是例子,經過仔細研究揣摩,總結出了裝飾器使用的本質規則,以備後查,希望對Python裝飾器有疑問的朋友有幫助。

首先要理解Python具備的這幾個特性:
1、用類物件呼叫一個方法,方法的第一個實參self就是物件本身,如果方法不是通過類物件呼叫,則self實參是你顯式傳的引數,例如通過裝飾器的方式傳遞,正是本文要 解釋的

這裡的幾處方法的呼叫都是通過物件的形式呼叫的,所以self形參就是呼叫者

2、任何物件都可以當作方法,比如類本身是一個方法,物件也是一個方法,方法更是一個方法
   為什麼類是方法:比如有一個類Cls,如果我們這樣用Cls(),那麼會預設呼叫建構函式__init__()
   為什麼物件是方法:比如obj=Cls(),那麼我們這樣用obj(),則預設會呼叫Cls類裡的__call__方法,當然__call__必須手動實現,美其名曰這個類實現了callable介面。
   為什麼方法是方法這個就不用解釋了,地球人都明白

好了,接下來看看什麼是裝飾器吧,我們直接看跨類裝飾
1、首先讓我們看看如何用一個類的方法裝飾另一個類中的方法

一、用Deco.dec來裝飾myFunc,實際上是把myFunc作為引數傳遞給了Deco.dec方法,並返回另一個方法extendFunc
    使得以後呼叫myFunc的地方會轉呼叫extendFunc
二、由於裝飾器語法的限制,用 Deco.dec裝飾myFunc時必須用Deco類來引用(Deco.dec是通過類引用方法)
    因此註定了dec方法為類方法
三、必須返回一個方法,這是裝飾器的約定,否則在呼叫myFunc的時候就不知道調什麼方法了
四、呼叫了myFunc的地方就轉而呼叫extendFunc,所以在執行extendFunc的時候第一個實參是mycls
五、必須至少保留一個形參,因為你不知道呼叫者會傳什麼引數,所以我們這裡可以使用可變引數*arg1和**arg2
六、被裝飾的方法變成了普通方法,而裝飾的方法則替代了被裝飾的方法

七、被裝飾的方法由於沒有經過物件引用,直接傳入裝飾器,變成了普通方法,所以self形參變成了普通引數

之前我們用方法類裝飾方法,我們現在用類來裝飾方法(其實也是用方法裝飾方法,因為類也是方法,請記住剛才的特性之一)

好了,最後進階看一下下面這個案例