在 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__
.
一些观察:
- 我认为它与
property
装饰器有关。
- 属性
.a
似乎从未被访问过。
- 如果我将
prop1
中的 return super().a
行替换为 return 5
之类的内容,则永远不会调用 __getattr__
方法。
- 如果我实际上让
Test
继承自具有属性 a
的 class,它的值是从 test.meth1()
返回的,而不是从 test.prop1
返回的.
有人可以解释一下这是怎么回事吗?我一直无法找到任何有用的信息来解决属性装饰器和 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).
它允许属性在无法生成值时回退到常规查找机制。
我正在学习 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__
.
一些观察:
- 我认为它与
property
装饰器有关。 - 属性
.a
似乎从未被访问过。 - 如果我将
prop1
中的return super().a
行替换为return 5
之类的内容,则永远不会调用__getattr__
方法。 - 如果我实际上让
Test
继承自具有属性a
的 class,它的值是从test.meth1()
返回的,而不是从test.prop1
返回的.
有人可以解释一下这是怎么回事吗?我一直无法找到任何有用的信息来解决属性装饰器和 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 anAttributeError
because name is not an instance attribute or an attribute in the class tree for self; or__get__()
of a name property raises AttributeError).
它允许属性在无法生成值时回退到常规查找机制。