2016-08-19 43 views
0

我讀了一些python的對象屬性查找(這裏:https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/#object-attribute-lookup)。Python 3 __getattribute__ vs點訪問行爲

似乎很直截了當,所以我想它(python3):

class A: 
    def __getattr__(self, attr): 
     return (1,2,3) 

a = A() 

a.foobar #returns (1,2,3) as expected 
a.__getattribute__('foobar') # raises AttributeError 

我的問題是沒有這兩個應該DIBE相同?

爲什麼第二個出現屬性錯誤?

顯然,答案是a.foobar的邏輯與a.__getattribute("foobar")的邏輯不同。根據data modela.foobar調用a.__getattribute("foobar"),如果它引發AttributeError,它會調用a.-__getattr__('foobar')

所以看起來文章在他們的圖中有一個錯誤。它是否正確?

另一個問題:a.foobar的真實邏輯在哪裏?我認爲這是在__getattribute__,但顯然不完全。

編輯: 不是

Difference between __getattr__ vs __getattribute__重複。 我在這裏問的是object.fooobject.__getattribute__("foo")之間有什麼不同。這不同於__getattr____getatribute__這是微不足道的...

+1

請先參考官方文檔:https://docs.python.org/3.5/reference/datamodel.html#object.__getattribute__ – thodnev

+0

將'a .__ getattribute __('foobar')'改爲'a .__ getattr __('foobar ')'看看會發生什麼。 – DeepSpace

+0

對此不感興趣......'__getattribute__'應該最終調用'__getattr__'。 'a.foobar'應該叫'__getattribute__'爲什麼? – deller

回答

4

很容易讓人覺得__getattribute__是超過它真正負責的印象。 thing.attr不直接轉換爲thing.__getattribute__('attr')__getattribute__不負責調用__getattr__

退回到__getattr__發生在位於__getattribute__之外的屬性訪問機器部分。屬性查找過程是這樣的:

  • 通過直接搜索找到__getattribute__方法的對象的類型的MRO,繞過常規屬性查找過程。
  • 嘗試__getattribute__
    • 如果__getattribute__返回了一些東西,屬性查找過程就完成了,那就是屬性值。
    • 如果__getattribute__引發了非AttributeError,則屬性查找過程完成,並且異常將傳播出查找。
    • 否則,__getattribute__引發了一個AttributeError。查找繼續。
  • 查找__getattr__方法與我們發現__getattribute__的方法相同。
    • 如果沒有__getattr__,則屬性查找過程完成,並且傳播來自__getattribute__的AttributeError。
  • 嘗試__getattr__,並返回或提高__getattr__返回或提高。

至少,就語言語義而言,它就是這樣工作的。就低層次實現而言,其中一些步驟可能會在不需要的情況下進行優化,並且存在我沒有描述過的C鉤(如tp_getattro)。除非您想深入瞭解CPython解釋器源代碼,否則您不必擔心這種事情。

+0

TL; DR'__getattribute__'只有在定義屬性時纔會繞過常規屬性查找,並且不打算調用'__getattr__'。直接在沒有定義它的類上調用'__getattribute__',會退回到'object .__ getattribute__'或其他基類,從而引發(可能)一個'AttributeError' –