为什么在 python 中覆盖 getattr 方法时没有无限循环

Why there is no infinite loop while overriding getattr method in python

根据我的理解,我正在尝试覆盖 getattr 方法 默认情况下,以下代码片段中应该存在无限循环 调用 object.__getattribute__(self,attr) 将调用覆盖的 getattr 方法,因为属性 'notpresent' 不存在于命名空间中,并且此过程将继续重复。谁能帮我弄清楚为什么这里没有观察到这种行为。

此外,我无法弄清楚为什么在使用点表示法访问属性时完成对 getattribute 的隐式调用时未引发 AttributeError 的原因,而当我们试图在方法中显式调用 getattribute 时第二次引发它

class Test(object):

    #Act as a fallback and is invoked when getattribute is unable to find attribute

    def __getattr__(self,attr):

        print "getattr is called"
        return object.__getattribute__(self,attr) #AttributeError is raised

t=Test([1,2,3,4])

b = t.notpresent

您正在 Test.__getattr__ 内呼叫 object.__getattribute__

这里不涉及循环。

此外,根据 the docs__getattribute__ 不会隐式调用 __getattr__

编辑后更新

Here__getattribute__ 调用的 C 实现。特别是 slot_tp_getattr_hook 部分。

在您的情况下,属性查找失败导致第 6072 行调用您的自定义 __getattr__ 函数。

从那时起,AttributeError 已被清除。但是您对 object.__getattribute__ 的调用会将其设置回去,而第 6074 行或 6075 行将不会处理它。

object.__getattribute__ 调用已实现 like so,因此(重新)引发 AttributeError(第 1107 行)。

因为 __getattribute__ 通常只在对象的 __dict__ 和类似地方查找属性 - 它不会隐式调用 __getattr__ 来检索属性。

请注意,如果 __getattribute__ 将调用 __getattr__,如果 __getattribute__ 未能找到该属性,则 __getattr__ 方法可能会被调用两次(因为查找应该调用 __getattr____getattribute__ 失败时)。