python裝飾器和描述器的使用總結

發表於2016-10-09

被某些中文教程坑過,我的建議是有問題看官方文件,即使沒有很詳細的例子,至少不坑

裝飾器

毫無疑問在python中用得非常多

f上加deco裝飾器相當於f = deco(f), 和functools.partial有些類似

如果被裝飾的函式f帶引數且有返回值

如果裝飾器帶有引數,需要多包一層,把引數呼叫包進去

只有最裡面一層的__deco才會每次都呼叫,其它外層函式只在包裝時呼叫一次,當然,你可以在其中宣告變數,然後拿到__deco裡使用。如果需要保留函式名,則在__deco上加@functools.wraps裝飾器

使用 作裝飾器,注意是此時相當於裝飾函式,被裝飾的函式會作為例項化引數,得到一個類例項,以python wiki上一個做登入檢查的程式碼為例

描述器

描述器在監視特定屬性的時候很有用,其只在新式類中起作用。所有的描述器協議如下:

descr.__get__(self, obj, type=None) --> value
descr.__set__(self, obj, value) --> None
descr.__delete__(self, obj) --> None

如果一個物件同時定義了 __get__()__set__(),它叫做資料描述器(data descriptor)。僅定義了 __get__() 的描述器叫非資料描述器
描述器在屬性訪問時被自動呼叫。舉例來說, obj.x 會在 obj 的字典中找x ,如果x定義了 __get__方法,那麼 x.__get__(obj)會依據下面的優先規則被呼叫

呼叫優先順序:
資料描述器 -> 例項字典 -> 非資料描述器

常用的描述器就是property了,一般都只實現了__get__的介面
先給出一個classmethod的實現和一個用於測試描述器優先順序的類

接下來呼叫

很明顯x是資料描述器,而name不是,所以結果是

3
5
{‘_data’: 3, ‘name’: ‘test’}

如果給classproperty加上__set__,那麼就會呼叫被裝飾的name,而不是例項化時例項字典中的name

一個property的python 實現

相關文章