我读了一下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
我的问题不是两个应该是完全相同的吗?
为什么第二个会引发属性错误?
显然,答案是a.foobar
的逻辑与a.__getattribute("foobar")
的逻辑不同。根据{{3}}:a.foobar
调用a.__getattribute("foobar")
,如果它引发了AttributeError,则会调用a.-__getattr__('foobar')
所以看来这篇文章在他们的图表中有错误。这是对的吗?
另一个问题:a.foobar的真正逻辑在哪里?我认为它在__getattribute__
,但显然不完全。
编辑: 不重复
data model。
我在这里问object.foo
和object.__getattribute__("foo")
之间有什么不同。这与__getattr__
vs __getatribute__
不同,这是微不足道的......
答案 0 :(得分:5)
很容易得到__getattribute__
比实际更负责的印象。 thing.attr
未直接翻译为thing.__getattribute__('attr')
,__getattribute__
不对调用__getattr__
负责。
__getattr__
的回退发生在__getattribute__
之外的属性访问机制部分。属性查找过程的工作方式如下:
__getattribute__
方法,绕过常规属性查找过程。__getattribute__
。
__getattribute__
返回了某些内容,则属性查找过程完成,这就是属性值。__getattribute__
引发了非AttributeError,则属性查找过程完成,异常传播出查找。__getattribute__
引发了一个AttributeError。查找继续。__getattr__
相同的方式查找__getattribute__
方法。
__getattr__
,则属性查找过程完成,__getattribute__
的AttributeError传播。__getattr__
,然后返回或提高__getattr__
返回或加注。至少,就语言语义而言,它就是这样的。就低级实现而言,其中一些步骤可能会在不必要的情况下进行优化,并且有一些我没有描述过的tp_getattro
之类的C钩子。除非你想深入了解CPython解释器源代码,否则你不必担心这种事情。