1

请注意,此问题已在评论中回答

我注意到一些异常处理行为__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__

无条件调用以实现类实例的属性访问。如果该类还定义了__getattr__(),则不会调用后者,除非__getattribute__()显式调用它或引发AttributeError.

由此,我猜想任何AttributeError加注__getattribute__都会被捕获,并且该过程会延迟到__getattr__,这样AttributeError('in __getattribute__')调用者就永远不会看到。

令我惊讶的是,不仅看到了错误,而且AttributeError引发的 onA().a也是 in 中的那个__getattribute__,就好像__getattr__从未被调用过一样。那是除非 __getattr__提出自己的

def __getattr__(self, item):
    raise AttributeError('in __getattr__')

在这种情况下,我们看到AttributeError('in __getattr__')了提升。

这里有什么规则?如果不是AttributeError('in __getattribute__')我提出了in 的一些子类Oops,它们是否适用?AttributeError__getattribute__

4

1 回答 1

0

总结评论。

[Python 3.Docs]:数据模型 - 对象。__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__'

虽然我可以理解为什么它可能会让某些人感到困惑,但从我所关心的(在多次浏览文档之后)来看,很清楚:
如果__getattr__是从object继承的,那么(引用的)文本“如果类也定义 __getattr__() " 没有意义

于 2019-09-01T13:48:06.323 回答