Python中__get__,__getattr__,__getattribute__的區(qū)別

__get__,__getattr__和__getattribute__都是訪問屬性的方法,但不太相同。

object.__getattr__(self, name)
當(dāng)一般位置找不到attribute的時(shí)候,會(huì)調(diào)用__getattr__,返回一個(gè)值或AttributeError異常

object.__getattribute__(self, name)
無條件被調(diào)用,通過實(shí)例訪問屬性。如果class中定義了__getattr__(),則__getattr__()不會(huì)被調(diào)用(除非顯示調(diào)用或引發(fā)AttributeError異常)

object.__get__(self, instance, owner)
如果class定義了它,則這個(gè)class就可以稱為descriptor。owner是所有者的類,instance是訪問descriptor的實(shí)例,如果不是通過實(shí)例訪問,而是通過類訪問的話,instance則為None。(descriptor的實(shí)例自己訪問自己是不會(huì)觸發(fā)__get__,而會(huì)觸發(fā)__call__,只有descriptor作為其它類的屬性才有意義。)(所以下文的d是作為C2的一個(gè)屬性被調(diào)用)

class C(object):  
    a = 'abc'  
    def __getattribute__(self, *args, **kwargs):  
        print("__getattribute__() is called")  
        return object.__getattribute__(self, *args, **kwargs)  
#        return "haha"  
    def __getattr__(self, name):  
        print("__getattr__() is called ")  
        return name + " from getattr"  
      
    def __get__(self, instance, owner):  
        print("__get__() is called", instance, owner)  
        return self  
      
    def foo(self, x):  
        print(x)  
  
class C2(object):  
    d = C()  
if __name__ == '__main__':  
    c = C()  
    c2 = C2()  
    print(c.a)  
    print(c.zzzzzzzz)  
    c2.d  
    print(c2.d.a)  

輸出結(jié)果是:

__getattribute__() is called  
abc  
__getattribute__() is called  
__getattr__() is called   
zzzzzzzz from getattr  
__get__() is called <__main__.C2 object at 0x16d2310> <class '__main__.C2'>  
__get__() is called <__main__.C2 object at 0x16d2310> <class '__main__.C2'>  
__getattribute__() is called  
abc  

小結(jié):可以看出,每次通過實(shí)例訪問屬性,都會(huì)經(jīng)過__getattribute__函數(shù)。而當(dāng)屬性不存在時(shí),仍然需要訪問__getattribute__,不過接著要訪問__getattr__。這就好像是一個(gè)異常處理函數(shù)。
每次訪問descriptor(即實(shí)現(xiàn)了__get__的類),都會(huì)先經(jīng)過__get__函數(shù)。

需要注意的是,當(dāng)使用類訪問不存在的變量是,不會(huì)經(jīng)過__getattr__函數(shù)。而descriptor不存在此問題,只是把instance標(biāo)識(shí)為none而已。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容