`__getattribute__` 和 `__getattr__` 中的错误处理
Posted
技术标签:
【中文标题】`__getattribute__` 和 `__getattr__` 中的错误处理【英文标题】:Error handling in `__getattribute__` and `__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)的含义。"
那么这里有什么问题呢?我没有看到。
【参考方案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__()”将没有意义 .
【讨论】:
以上是关于`__getattribute__` 和 `__getattr__` 中的错误处理的主要内容,如果未能解决你的问题,请参考以下文章
python中__getattr__和__getattribute__区别
关于__getattr__和__getattribute__的一些问题?
python中__get__,__getattr__,__getattribute__的区别