詳解Python中的descriptor描述器簡明使用指南

來源:互聯網
上載者:User
descriptor在Python中主要被用來定義方法和屬性,使用起來相當具有技巧性,這裡我們先從基礎的開始,整理一份Python中的descriptor描述器簡明使用指南

當定義迭代器的時候,描述是實現迭代協議的對象,即實現__iter__方法的對象。同理,所謂描述器,即實現了描述符協議,即__get__, __set__, 和 __delete__方法的對象。

單看定義,還是比較抽象的。talk is cheap。看代碼吧:

class WebFramework(object):  def __init__(self, name='Flask'):    self.name = name  def __get__(self, instance, owner):    return self.name  def __set__(self, instance, value):    self.name = valueclass PythonSite(object):  webframework = WebFramework()In [1]: PythonSite.webframeworkOut[1]: 'Flask'In [2]: PythonSite.webframework = 'Tornado'In [3]: PythonSite.webframeworkOut[3]: 'Tornado'

定義了一個類WebFramework,它實現了描述符協議__get__和__set__,該對象(類也是對象,一切都是對象)即成為了一個描述器。同時實現__get__和__set__的稱之為資料描述器(data descriptor)。僅僅實現__get__的則為非描述器。兩者的差別是相對於執行個體的字典的優先順序。

如果執行個體字典中有與描述器同名的屬性,如果描述器是資料描述器,優先使用資料描述器,如果是非資料描述器,優先使用字典中的屬性。

描述器的調用
對於這類魔法,其調用方法往往不是直接使用的。例如裝飾器需要用 @ 符號調用。迭代器通常在迭代過程,或者使用 next 方法調用。描述器則比較簡單,對象屬性的時候會調用。

In [15]: webframework = WebFramework()In [16]: webframework.__get__(webframework, WebFramework)Out[16]: 'Flask'

描述器的應用
描述器的作用主要在方法和屬性的定義上。既然我們可以重新描述類的屬性,那麼這個魔法就可以改變類的一些行為。最簡單的應用則是可以配合裝飾器,寫一個類屬性的緩衝。Flask的作者寫了一個werkzeug網路工具庫,裡面就使用描述器的特性,實現了一個緩衝器。

class _Missing(object):  def __repr__(self):    return 'no value'  def __reduce__(self):    return '_missing'_missing = _Missing()class cached_property(object):  def __init__(self, func, name=None, doc=None):    self.__name__ = name or func.__name__    self.__module__ = func.__module__    self.__doc__ = doc or func.__doc__    self.func = func  def __get__(self, obj, type=None):    if obj is None:      return self    value = obj.__dict__.get(self.__name__, _missing)    if value is _missing:      value = self.func(obj)      obj.__dict__[self.__name__] = value    return valueclass Foo(object):  @cached_property  def foo(self):    print 'first calculate'    result = 'this is result'    return resultf = Foo()print f.foo  # first calculate this is resultprint f.foo  # this is result

運行結果可見,first calculate只在第一次調用時候被計算之後就把結果緩衝起來了。這樣的好處是在網路編程中,對HTTP協議的解析,通常會把HTTP的header解析成python的一個字典,而在視圖函數的時候,可能不知一次的訪問這個header,因此把這個header使用描述器緩衝起來,可以減少多餘的解析。

描述器在python的應用十分廣泛,通常是配合裝飾器一起使用。強大的魔法來自強大的責任。描述器還可以用來實現ORM中對sql語句的"先行編譯"。恰當的使用描述器,可以讓自己的Python代碼更優雅。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.