【问题标题】:Error handling in `__getattribute__` and `__getattr__``__getattribute__` 和 `__getattr__` 中的错误处理
【发布时间】:2020-01-04 19:59:58
【问题描述】:

注意此问题已在 cmets 中得到解答

我注意到__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

由此,我猜想__getattribute__ 中引发的任何AttributeError 总是会被捕获,并且该过程会延迟到__getattr__,这样调用者就永远不会看到AttributeError('in __getattribute__')

令我惊讶的是,不仅看到了错误,而且在A().a 上引发的AttributeError__getattribute__ 中的错误,好像从未调用过__getattr__。那是 除非 __getattr__ 提出自己的

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

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

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

【问题讨论】:

  • If the class also defines __getattr__() - 你的班级没有定义__getattr__
  • @snakecharmerb 很好奇,继承自 object__getattr__ 会发生什么?
  • 奇怪 - object 上没有 __getattr__(试试 object.__getattr__)。那么object.__getattr__ 的文档是什么意思?
  • ah, "可以定义以下方法来自定义类实例的属性访问(使用、分配或删除 x.name)的含义。"
  • 那么这里有什么问题呢?我没有看到。

标签: python exception python-datamodel


【解决方案1】:

总结 cmets。

[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 继承的,那么(引用的)文本“If the class also defined __getattr__()”将没有意义 .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 2019-09-02
    • 2020-04-26
    相关资源
    最近更新 更多