我读了一些关于 python 的对象属性查找的内容(这里:https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/#object-attribute-lookup 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")
。根据数据模型 https://docs.python.org/3.5/reference/datamodel.html#object.__getattribute__: a.foobar
calls a.__getattribute("foobar")
如果它引发 AttributeError,它会调用a.-__getattr__('foobar')
所以看来这篇文章的图表有错误。它是否正确?
还有一个问题:真正的逻辑在哪里?a.foobar
坐?我以为是在__getattribute__
但显然不完全是。
Edit:
不是重复的
__getattr__ 与 __getattribute__ 之间的区别 https://stackoverflow.com/questions/3278077/difference-between-getattr-vs-getattribute。
我在这里问有什么不同object.foo
and object.__getattribute__("foo")
。这不同于__getattr__
vs __getatribute__
这是微不足道的...
很容易给人这样的印象__getattribute__
所承担的责任比实际承担的要多。thing.attr
不直接翻译为thing.__getattribute__('attr')
, and __getattribute__
不负责打电话__getattr__
.
回退到__getattr__
发生在属性访问机制外部的部分__getattribute__
。属性查找过程如下:
- 找出
__getattribute__
通过直接搜索对象类型的方法MRO https://www.python.org/download/releases/2.3/mro/,绕过常规属性查找过程。
- Try
__getattribute__
.
- If
__getattribute__
返回了一些东西,属性查找过程就完成了,这就是属性值。
- If
__getattribute__
引发非 AttributeError,属性查找过程完成,并且异常从查找中传播出去。
- 否则,
__getattribute__
引发了一个 AttributeError。查找仍在继续。
- Find the
__getattr__
method the same way we found __getattribute__
.
- 如果没有
__getattr__
,属性查找过程完成,并且 AttributeError 来自__getattribute__
传播。
- Try
__getattr__
,并返回或提高任何内容__getattr__
回报或加薪。
至少,就语言语义而言,它是这样工作的。就低级实现而言,其中一些步骤可能会在不必要的情况下被优化,并且有类似的 C 钩子tp_getattro
我还没有描述过。除非您想深入研究 CPython 解释器源代码,否则您无需担心此类事情。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)