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

在python类属性中访问'super()',python,inheritance,python-decorators,Python,Inheritance,Python Decorators,我正在学习python的继承,遇到了一个我不太理解的行为。下面是一个简单的工作示例: class Test(): def meth1(自身): 打印('1') 返回super().a#调用随机不存在属性;错误(如预期的那样) @财产 def prop1(自身): 打印('访问prop1') 返回super().a#调用随机不存在属性;没有错误? def _ugetattr _;(self,name): 打印('getattr'+名称) 测试=测试() 调用.meth1()按预期失败 In [

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

class Test():
def meth1(自身):
打印('1')
返回super().a#调用随机不存在属性;错误(如预期的那样)
@财产
def prop1(自身):
打印('访问prop1')
返回super().a#调用随机不存在属性;没有错误?
def _ugetattr _;(self,name):
打印('getattr'+名称)
测试=测试()
调用
.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'
…我不明白。该属性似乎被调用了两次,一次是“正常”调用,一次是通过
\uuu getattr\uuu
调用

一些意见:

  • 我想这与
    属性
    装饰器有关
  • 属性
    .a
    似乎永远无法访问
  • 如果我将
    prop1
    中的
    return super().a
    行替换为类似
    return 5
    的内容,则永远不会调用
    \u getattr\u
    方法
  • 如果我实际使
    Test
    从具有属性
    a
    的类继承,则其值将从
    Test.meth1()
    返回,而不是从
    Test.prop1
    返回
有人能解释一下这是怎么回事吗?我找不到任何关于属性装饰器和
super()
组合的有用信息


非常感谢,

TLDR:
meth1
在不涉及
\uu getattr\uuu
的情况下,在查找后引发
属性错误
prop1
在查找过程中引发
AttributeError
,触发返回到
\uuuu getattr\uuuuu
的回退,该回退成功返回
None

>test.prop1#AttributeError在查找过程中发生在此处
访问prop1
getattr prop1
>>>meth=test.meth1#AttributeError在查找过程中发生*不是*
>>>meth()#AttributeError发生在此处*在*查找之后
...
AttributeError:“超级”对象没有属性“a”

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

class Test():
@财产
def prop1(自身):
打印('访问prop1')
raise AttributeError替换'super().a`
def _ugetattr _;(self,name):
打印('getattr'+名称)
测试=测试()
test.prop1#<显式引发AttributeError
#访问prop1
#getattr prop1
test.prop2#<隐式引发AttributeError
#getattr prop2
AttributeError
不会显示它是来自缺少的
prop1
属性还是某个嵌套的内部属性(例如,
super().a
)。因此,两者都会触发回退到
\uu getattr\uu

这是
的预期行为

当默认属性访问失败且出现AttributeError时调用(由于名称不是实例属性或类树中的属性,因此,
\uuuuuGetAttribute\uuuuuuuuuuuuuuoRor()
引发一个
AttributeError
;或者名称属性的
\uuuuuGet\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuoCode>引发AttributeError)


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

在这种情况下,
属性
似乎正在抑制
属性错误
。这不是关于
super
;属性中的显式
raise AttributeError
也被静默。我是否理解正确?我要拟人化。要执行
meth1
,首先需要在对象内部字典中查找它。它被找到并加载到内存中。“Python知道此对象上存在此方法”。然后抛出一个
AttributeError
,但这不会引起混淆,这可能是因为对象上缺少属性,所以我们不会进入
\uuuuuuuGetAttr\uuuuuuuuu
。(1/2)与属性不同
prop1
“模拟”一个简单的有值属性的存在(就好像它是
self.prop1
),显然,属性
prop1
只有在对其值进行无误评估后才假定存在。由于没有发生这种情况,python假定
AttributeError
表示它不存在,并使用
\uuuu getattr\uuuuu
检查是否定义了回退,即返回
None
。(2/2)@ElRudi是的,就是这样。查找方法和调用方法是两件不同的事情。您可以将
test.meth1
分为a)
tmeth1=test.meth1()
和b)
tmeth1()
。值得注意的是,a)进行查找(可能包括
\uu getattr\uuu
),但b)会引发
属性错误。属性是作为查找的一部分调用的,因此只有A)和
AttributeError
。非常好,非常感谢。这是否意味着这种行为一般不适用于装饰师?它是否仅仅因为执行了它所修饰的函数就适用于
属性
。您可以通过调用语法构建一个
属性
,或者插入一个预构建的属性,其行为在这里也一样。重要的部分是对象
@属性
+函数构造什么;即在
\uuuuu get\uuuu
过程中引发错误的内容(在这种情况下,通过调用
\uuuuu get\uuuu
函数)。比较
@classmethod
,它不会抑制错误。
In  [2]: test.prop1
accessing prop1
getattr prop1