注意,这些问题会在评论中得到解答
我注意到__getattribute__
和__getattr__
中的一些异常处理行为,在文档或此处的其他帖子中都找不到。
考虑此类A
。如果A
的实例具有None
的属性,则访问该属性将引发AttributeError
。
class A:
def __getattribute__(self, item):
value = object.__getattribute__(self, item)
if value is None:
raise AttributeError('in __getattribute__')
return value
def __init__(self, a=None):
self.a = a
A(1).a # 1
A().a # raises AttributeError('in __getattribute__')
现在,__getattribute__
上的docs说
无条件调用以实现类实例的属性访问。如果该类还定义了
__getattr__()
,则除非__getattribute__()
显式调用它或引发AttributeError
,否则后者将不会被调用。
据此,我猜想AttributeError
中提出的任何__getattribute__
都将始终被捕获,并且该过程将推迟到__getattr__
,这样AttributeError('in __getattribute__')
将永远不会被看到由来电者提供。
令我惊讶的是,不仅看到了错误,而且在AttributeError
上引发的A().a
是__getattribute__
中的错误,好像从未调用过__getattr__
一样。那是除非 __getattr__
自己提出
def __getattr__(self, item):
raise AttributeError('in __getattr__')
在这种情况下,我们看到的是AttributeError('in __getattr__')
。
这里有什么规则?如果我在AttributeError('in __getattribute__')
中引发了Oops
的某个子类AttributeError
而不是__getattribute__
,它们是否适用?
答案 0 :(得分:0)
总结评论。
[Python 3.Docs]: Data model - object.__getattribute__(self, name)(强调是我的)状态:
无条件调用以实现类实例的属性访问。 如果该类还定义了__getattr__() ,则除非__getattribute__()显式调用或引发AttributeError,否则不会调用后者。此方法应返回(计算出的)属性值或引发AttributeError异常。为了避免此方法中的无限递归,其实现应始终使用相同的名称调用基类方法以访问其所需的任何属性,例如
object.__getattribute__(self, name)
。
混淆是因为假设 __ getattr __ 是从 object 继承的(这是错误的):
>>> dir(object) ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] >>> >>> object.__getattribute__ <slot wrapper '__getattribute__' of 'object' objects> >>> object.__getattr__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'object' has no attribute '__getattr__'
尽管我可以理解,但从我所关注的角度(多次阅读 doc 之后),为什么它可能会使某些人感到困惑,但很清楚:
如果 __ getattr __ 是从 object 继承的,然后(带引号的)文本“ 如果该类还定义了__getattr __()” >。