访问python类属性中的' super() '



我正在学习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

…我不明白似乎该属性被调用两次,一次是"正常",一次是通过__getattr__

一些观察:

  • 我想这与property装饰器有关。
  • 属性.a似乎永远不会被访问。
  • 如果我用return 5之类的东西替换prop1中的return super().a行,则永远不会调用__getattr__方法。
  • 如果我实际上使Test从具有属性a的类继承,其值从test.meth1()返回,而不是从test.prop1返回。

谁能解释一下这是怎么回事?我没能找到任何有用的信息来解决属性装饰器和super()的组合。

许多谢谢,

TLDR:meth1在查找之后引发AttributeError,此时不涉及__getattr__prop1在查找时引发AttributeError,触发回退到__getattr__,并成功返回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)

当默认属性访问失败并产生AttributeError时调用(__getattribute__()抛出AttributeError,因为name不是实例属性或self的类树属性;__get__()的name属性会引发AttributeError ()。

当属性不能产生值时,它允许属性回退到常规查找机制。

最新更新