首頁 >後端開發 >Python教學 >Python中descriptor的詳細介紹

Python中descriptor的詳細介紹

巴扎黑
巴扎黑原創
2017-09-16 10:02:151410瀏覽

本文給大家分Python 中的descriptor相關知識,非常不錯,具有參考借鑒價值,需要的朋友參考下吧

定義

通常,一個descriptor 是具有「綁定行為」的物件屬性。所綁定行為可透過 descriptor 協定被自訂的 __get__() , __set__() 和 __delete__() 方法重寫。如果一個物件的上述三個方法任意一個被重寫,則可稱為 descriptor。

屬性的預設操作是從物件字典中取得、設定和刪除一個屬性。例如,a.x 有一個查找鏈,先 a.__dict__['x'] ,若沒有則 type(a).__dict__['x'] ,若沒有增往上查找父類直到元類。如果查找鏈中,物件被定義了 descriptor 方法,Python 就會覆寫預設行為。

Descriptor 是一個強大的工具,雖然開發者不常接觸到它,但它其實就是類別、屬性、函數、方法、靜態方法、類別方法以及 super() 背後的運作機制。

Descriptor 協定

三個方法原型如下:


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

資料descriptor 是同時具有_ _get__() 和__set__() 方法的對象,若只有__get__() 方法,則為非資料descriptor。如果實例字典中有和資料 descriptor 同名的入口,則資料 descriptor 優先權更高。相反,非資料 descriptor 優先權低。

讓 __set__() 方法拋出異常,就能建立一個只讀資料 descriptor。

呼叫 descriptor

descriptor 可以直接透過方法名稱呼叫。例如, d.__get__(obj) 。

而透過存取物件屬性,自動呼叫 descriptor 才是更通用的做法。例如,如果 d 定義了方法 __get__() ,則 obj.d 會呼叫 d.__get__(obj) 。

對於對象, b.x 會被轉換成 type(b).__dict__['x'].__get__(b, type(b)) 。而對於類別(是的,類別也可以呼叫), B.x 會被轉換成 B.__dict__['x'].__get__(None, B) 。

Descriptor 範例


class RevealAccess(object):
  """A data descriptor that sets and returns values
    normally and prints a message logging their access.
  """
  def __init__(self, initval=None, name='var'):
    self.val = initval
    self.name = name
  def __get__(self, obj, objtype):
    print('Retrieving', self.name)
    return self.val
  def __set__(self, obj, val):
    print('Updating', self.name)
    self.val = val
>>> class MyClass(object):
...   x = RevealAccess(10, 'var "x"')
...   y = 5
...
>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5

以上是Python中descriptor的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn