__getattribute__()、__getattr__()、__setattr__()、__delattr__()


物件本身可以定義__getattribute__()、__getattr__()__setattr__()__delattr__()等方法,以決定存取特性的行為:
def __getattribute__(self, name)
def __getattr__(self, name)
def __setattr__(self, name, value)
def __delattr__(self, name)

__getattribute__()最容易解釋,一但定義有這個方法,任何特性的尋找都會被攔截,即使是那些__xxx__的內建特性名稱。

__getattr__()的作用,是作為尋找特性的最後一個機會,如果同時定義有__getattribute__()、__getattr__()在尋找特性時的順序是:
  1. 如果有定義__getattribute__(),則傳回__getattribute__()的值
  2. 在產生實例的類別__dict__中尋找是否有相符的特性名稱。如果找到 且實際是個資料描述器,傳回__get__ ()方法的值。如果是個非資料描述器,則進行第2步
  3. 在實例的__dict__中尋找是否有相符的特性名稱,如果有則傳回值
  4. 在產生實例的類別__dict__中尋找是否有相符的特性名稱。如果不是非資料描述器則直接傳回特性值。如果是個非資料描述器(此時一定是僅具有__get__()方法),則傳回__get__()的值
  5. 如 果實例有定義__getattr__(),則傳回__getattr__()的值
  6. 如果實例沒有定義 __getattr__(),則丟出AttributeError

取得特性順序記憶的原則是:實例的__getattribute__()、資料描述器的__get__()、實例的__dict__、非資料描述器的__get__()、實例的__getattr__()。

__setattr__()的作用,在於攔截所有對實例的特性設定,如果對實例有個設定特性的動作,則設定的順序如下:
  1. 如果有定義__setattr__()則呼叫,如果沒有進行下一步
  2. 在產生實例的類別上,看看__dict__是否有相符合的特性名稱。如果找到 且實際是個資料描述器,則呼叫描述器的__set__()方法(如果沒有__set__()方法則丟出AttributeError),如果不是則進行下一步
  3. 在實例的__dict__上設定特性與值

設定特性順序記憶的原則是:實例的__setattr__()、資料描述器的__set__()、實例的__dict__。

__delattr__()的作用,在於攔截所有對實例的特性設定,如果對實例有個刪除特性的動作,則刪除的順序如下:
  1. 如果有定義__delattr__()則呼叫,如果沒有進行下一步
  2. 在產生實例的類別上,看看__dict__是否有相符合的特性名稱。如果找到 且實際是個資料描述器,則呼叫描述器的__delete__()方法(如果沒有__delete__()方法則丟出AttributeError),如果不是資料描述器則進行下一步
  3. 在實例的__dict__上找看看有無相符合的特性名稱,如果有則刪除,如果沒有則丟出AttributeError

刪除特性順序記憶的原則是:實例的__delattr__()、資料描述器的__delete__()、實例的__dict__。