在 python class 属性 中访问 `super()`

Accessing `super()` inside python class property

我正在学习 python 的继承,遇到了一个我不太理解的行为。这是一个最小的工作示例:

class Test():
    
    def meth1(self):
        print('accessing meth1')
        return super().a #calling random nonexisting attribute; error (as expected)
    
    @property
    def prop1(self):
        print('accessing prop1')
        return super().a #calling random nonexisting attribute; no error?

    def __getattr__(self, name):
        print('getattr ' + name)
    
test = Test()

调用 .meth1() 按预期失败...

In  [1]: test.meth1()
accessing meth1
Traceback (most recent call last):

  File "<ipython-input-160-4a0675c95211>", line 1, in <module>
    test.meth1()

  File "<ipython-input-159-1401fb9a0e13>", line 5, in meth1
    return super().a #calling random nonexisting attribute; error (as expected)

AttributeError: 'super' object has no attribute 'a'

...因为 super()object 确实没有这个属性。

但是.prop1没有...

In  [2]: test.prop1
accessing prop1
getattr prop1

...我不明白。 属性 似乎被调用了两次,一次是 'normally' 一次是通过 __getattr__.

一些观察:

有人可以解释一下这是怎么回事吗?我一直无法找到任何有用的信息来解决属性装饰器和 super().

的组合

非常感谢,

TLDR:meth1 在 查找后引发 AttributeError ,当 __getattr__ 不涉及时。 prop1 查找期间引发 AttributeError ,触发回退到 __getattr__ 继 return None.

>>> test.prop1        # AttributeError happens here during lookup
accessing prop1
getattr prop1
>>> meth = test.meth1 # AttributeError happens *not* here during lookup
>>> meth()            # AttributeError happens here *after* lookup
...
AttributeError: 'super' object has no attribute 'a'

__getattr__ 方法仅在“未找到属性”时调用 – 换句话说,AttributeError 在访问时引发。 属性 直接引发错误时会发生相同的行为:

class Test():
    @property
    def prop1(self):
        print('accessing prop1')
        raise AttributeError  # replaces `super().a`

    def __getattr__(self, name):
        print('getattr ' + name)
    
test = Test()
test.prop1  # < explicitly raises AttributeError
# accessing prop1
# getattr prop1
test.prop2  # < implicitly raises AttributeError
# getattr prop2

AttributeError 不会显示它是来自缺失的 prop1 属性还是某些嵌套的内部属性(例如,super().a)。因此,两者都触发回退到 __getattr__.

这是 __getattr__ 的预期行为。

object.__getattr__(self, name)

Called when the default attribute access fails with an AttributeError (either __getattribute__() raises an AttributeError because name is not an instance attribute or an attribute in the class tree for self; or __get__() of a name property raises AttributeError).

它允许属性在无法生成值时回退到常规查找机制。