`__getattribute__`和`__getattr__`中的错误处理

时间:2019-09-01 11:58:10

标签: python exception python-datamodel

注意,这些问题会在评论中得到解答

我注意到__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__,它们是否适用?

1 个答案:

答案 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 __() >。