我在和__getattr__
斗争。我有一个复杂的递归代码库,在这里让异常传播是很重要的。
class A(object):
@property
def a(self):
raise AttributeError('lala')
def __getattr__(self, name):
print('attr: ', name)
return 1
print(A().a)
结果:
('attr: ', 'a')
1
为什么会有这种行为?为什么没有抛出异常?这种行为没有记录(^{getattr()
可以使用A.__dict__
。有什么想法吗?
^{} documentation 说:
我读到这篇文章(作者inclusio unius est exclusio alterius)时说,如果} 应该“返回(计算的)属性值或引发
object.__getattribute__
(即“无条件调用以实现属性访问”)碰巧引发AttributeError
,则属性访问将调用__getattr__
;注意^{AttributeError
异常”。作为类比,运算符特殊方法可以引发
NotImplementedError
,然后尝试其他运算符方法(例如__radd__
用于__add__
)。在同一个类中使用
__getattr__
和属性是危险的,因为这会导致很难调试的错误。如果属性的getter抛出
AttributeError
,那么AttributeError
将被静默捕获,并调用__getattr__
。通常,这会导致__getattr__
失败并出现异常,但如果您非常不走运,则不会,甚至无法轻松地将问题追溯到__getattr__
。除非您的属性getter很简单,否则您永远无法100%确定它不会抛出
AttributeError
。异常可能被抛出几个级别。以下是您可以做的:
__getattr__
。try ... except
块AttributeError
@property
decorator,它捕获AttributeError
,并将其重新抛出为RuntimeError
。另见http://blog.devork.be/2011/06/using-getattr-and-property_17.html
编辑:如果有人在考虑解决方案4(我不推荐),可以这样做:
然后在重写
__getattr__
的类中使用@property_
,而不是@property
。我刚把密码改成
而且,正如我们所看到的,事实上,这一财产是先受审判的。但由于它声称不存在(通过提高
AttributeError
),因此__getattr__()
被称为“最后的手段”。它没有明确的文档记录,但是可以在“当属性查找在通常的位置没有找到属性时调用”下计算。
相关问题 更多 >
编程相关推荐