Python 3 __getattribute__ vs dot access behavior

I read a little search for the python object attribute (here: https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/#object-attribute-lookup ).

It seems pretty straight forward, so I tried (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 

My question is not that both should be the same?

Why does the second cause an attribute error?

Therefore, the answer seems to be that the logic for a.foobar IS is different from the logic for a.__getattribute("foobar") . According to the data model : a.foobar calls a.__getattribute("foobar") , and if it calls the AttributeError attribute, it calls a.-__getattr__('foobar')

So it seems that the article is wrong in its diagram. Is it correct?

And one more question: where is the real logic for a.foobar sitting? I thought it was in __getattribute__ , but apparently not completely.

Edit: Not a duplicate

The difference between __getattr__ vs __getattribute__ . I ask what is the difference between object.foo and object.__getattribute__("foo") . This is different from __getattr__ vs __getatribute__ , which is trivial ...

0
source share
1 answer

It is easy to get the impression that __getattribute__ is responsible for more than it really is. thing.attr does not translate directly to thing.__getattribute__('attr') , and __getattribute__ not responsible for calling __getattr__ .

The rejection of __getattr__ occurs in that part of the attribute access mechanism that is outside of __getattribute__ . The attribute search process works as follows:

  • Find the __getattribute__ method by directly searching for the type of the MRO object, bypassing the normal attribute search process.
  • Try __getattribute__ .
    • If __getattribute__ returns something, the attribute search process is complete and that attribute value.
    • If __getattribute__ non-AttributeError, the attribute lookup process is complete and the exception is thrown out of view.
    • Otherwise, __getattribute__ raised an AttributeError. The search continues.
  • Find the __getattr__ method in the same way as we found __getattribute__ .
    • If __getattr__ not __getattr__ , the attribute search process is completed, and the AttributeError attribute from __getattribute__ propagated.
  • Try __getattr__ and return or raise anything that __getattr__ will return or raise.

At least in terms of language semantics, it works like this. As for the low-level implementation, some of these steps can be optimized when they are not needed, and there are C-hooks like tp_getattro that I have not described. You do not need to worry about this if you do not want to dive into the source code of the CPython interpreter.

+4
source

Source: https://habr.com/ru/post/1269640/


All Articles