Python 3 __getattribute__ vs点访问行为

del*_*ler 1 python python-3.x

我读了一下python的对象属性查找(这里:https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/#object-attribute-lookup).

看起来很直接,所以我试了一下(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
Run Code Online (Sandbox Code Playgroud)

我的问题是不是两个应该是相同的?

为什么第二个会引发属性错误?

所以答案显然是a.foobarIS的逻辑不同于逻辑a.__getattribute("foobar").根据数据模型:a.foobar调用a.__getattribute("foobar"),如果它引发AttributeError,则调用a.-__getattr__('foobar')

所以看来这篇文章在他们的图表中有一个错误.它是否正确?

还有一个问题:a.foobar的真正逻辑在哪里?我认为它在__getattribute__但显然不完全.

编辑: 不重复

__getattr__与__getattribute__之间的区别.我问这里有什么之间的不同object.fooobject.__getattribute__("foo").这__getattr__与vs 不同,__getatribute__这是微不足道的......

use*_*ica 6

获得__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__回报或加注.

至少,就语言语义而言,它就是这样的.就低级实现而言,这些步骤中的一些可以在不需要的情况下进行优化,并且存在类似于tp_getattro我未描述的C钩子.除非你想深入了解CPython解释器源代码,否则你不必担心这种事情.