python,getattr

http://www.4pang.com/2010/08/20/4%E8%83%96%E5%AD%A6python-%EF%BC%8D-__getattr__-%E5%92%8C-__getattribute__-%E6%96%B9%E6%B3%95%E7%9A%84%E5%8C%BA%E5%88%AB.htmlhtml

python 再訪問屬性的方法上定義了__getattr__() 和 __getattribute__() 2種方法,其區別很是細微,但很是重要。python

  1. 若是某個類定義了 __getattribute__() 方法,在 每次引用屬性或方法名稱時 Python 都調用它(特殊方法名稱除外,由於那樣將會致使討厭的無限循環)。
  2. 若是某個類定義了 __getattr__() 方法,Python 將只在正常的位置查詢屬性時纔會調用它。若是實例 x 定義了屬性 color, x.color 將 不會 調用x.__getattr__('color');而只會返回 x.color 已定義好的值。

 

讓咱們用兩個例子來解釋一下:編碼

>>> dyn = Dynamo()
>>> dyn.color'PapayaWhip'>>> dyn.color = 'LemonChiffon'
>>> dyn.color'LemonChiffon'class Dynamo(object):
    def __getattr__(self, key):
 if key == 'color': ①
            return 'PapayaWhip'
        else:
 raise AttributeError ②
  1. 屬性名稱以字符串的形式傳入 __getattr()__ 方法。若是名稱爲 'color',該方法返回一個值。(在此狀況下,它只是一個硬編碼的字符串,但能夠正常地進行某些計算並返回結果。)
  2. 若是屬性名稱未知, __getattr()__ 方法必須引起一個 AttributeError 例外,不然在訪問未定義屬性時,代碼將只會默默地失敗。(從技術角度而言,若是方法不引起例外或顯式地返回一個值,它將返回 None ——Python 的空值。這意味着 全部 未顯式定義的屬性將爲 None,幾乎能夠確定這不是你想看到的。)
  3. dyn 實例沒有名爲 color 的屬性,所以在提供計算值時將調用 __getattr__() 。
  4. 在顯式地設置 dyn.color 以後,將再也不爲提供 dyn.color 的值而調用 __getattr__() 方法,由於 dyn.color 已在該實例中定義。

另外一方面,__getattribute__() 方法是絕對的、無條件的。spa

>>> dyn = SuperDynamo()
>>> dyn.color'PapayaWhip'>>> dyn.color = 'LemonChiffon'
>>> dyn.color'PapayaWhip'class SuperDynamo(object):
    def __getattribute__(self, key):
        if key == 'color':
            return 'PapayaWhip'
        else:
            raise AttributeError
  1. 在獲取 dyn.color 的值時將調用 __getattribute__() 方法。
  2. 即使已經顯式地設置 dyn.color,在獲取 dyn.color 的值時, 仍將調用 __getattribute__() 方法。若是存在 __getattribute__() 方法,將在每次查找屬性和方法時 無條件地調用 它,哪怕在建立實例以後已經顯式地設置了屬性。

☞若是定義了類的 __getattribute__() 方法,你可能還想定義一個 __setattr__() 方法,並在二者之間進行協同,以跟蹤屬性的值。不然,在建立實例以後所設置的值將會消失在黑洞中。code

必須特別當心 __getattribute__() 方法,由於 Python 在查找類的方法名稱時也將對其進行調用。htm

>>> hero = Rastan()
>>> hero.swim()Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __getattribute__
AttributeErrorclass Rastan(object):
    def __getattribute__(self, key):
 raise AttributeError ①
    def swim(self):
        pass
  1. 該類定義了一個老是引起 AttributeError 例外的 __getattribute__() 方法。沒有屬性或方法的查詢會成功。
  2. 調用 hero.swim() 時,Python 將在 Rastan 類中查找 swim() 方法。該查找將執行整個 __getattribute__()方法,由於全部的屬性和方法查找都經過__getattribute__() 方法。在此例中, __getattribute__() 方法引起 AttributeError 例外,所以該方法查找過程將會失敗,而方法調用也將失敗。
相關文章
相關標籤/搜索