Dav*_*ter 13 python exception-handling exception python-2.7 python-3.x
我正在努力__getattr__.我有一个复杂的递归代码库,让异常传播很重要.
class A(object):
@property
def a(self):
raise AttributeError('lala')
def __getattr__(self, name):
print('attr: ', name)
return 1
print(A().a)
Run Code Online (Sandbox Code Playgroud)
结果是:
('attr: ', 'a')
1
Run Code Online (Sandbox Code Playgroud)
为什么会这样?为什么没有例外?此行为未记录(__getattr__文档).getattr()可以使用A.__dict__.有什么想法吗?
我只是将代码更改为
class A(object):
@property
def a(self):
print "trying property..."
raise AttributeError('lala')
def __getattr__(self, name):
print('attr: ', name)
return 1
print(A().a)
Run Code Online (Sandbox Code Playgroud)
而且,正如我们所见,确实首先尝试了财产.但是,因为它声称不在那里(通过提高AttributeError),__getattr__()被称为"最后的手段".
它没有明确记录,但可以计入"当属性查找没有在通常的位置找到属性时调用".
__getattr__在同一个类中使用和属性是危险的,因为它可能导致很难调试的错误.
如果属性的getter抛出AttributeError,则会AttributeError被静默捕获,并被__getattr__调用.通常情况下,这会导致__getattr__异常失败,但如果您非常不走运,则不会,并且您甚至无法轻松追溯问题__getattr__.
除非你的财产获取者是微不足道的,否则你永远不能100%确定它不会抛出AttributeError.异常可能会被抛出几个层次.
这是你可以做的:
__getattr__在同一个类中使用属性.try ... except块添加到所有非常重要的属性getterAttributeError@property装饰器版本,将其捕获AttributeError并重新抛出RuntimeError.另见http://blog.devork.be/2011/06/using-getattr-and-property_17.html
编辑:如果有人正在考虑解决方案4(我不推荐),它可以这样做:
def property_(f):
def getter(*args, **kwargs):
try:
return f(*args, **kwargs)
except AttributeError as e:
raise RuntimeError, "Wrapped AttributeError: " + str(e), sys.exc_info()[2]
return property(getter)
Run Code Online (Sandbox Code Playgroud)
然后使用@property_而不是@property覆盖的类__getattr__.
如果类也定义
__getattr__(),除非__getattribute__()明确调用它或引发一个,否则不会调用后者AttributeError.
我读到这个(通过inclusio unius est exclusio alterius)说,属性访问将调用__getattr__if object.__getattribute__(" 无条件地实现属性访问 ")恰好引发AttributeError- 无论是直接还是在描述符内部__get__(例如属性fget); 请注意__get__应该" 返回(计算的)属性值或引发AttributeError异常 ".
作为类比,操作员特殊方法可以提出NotImplementedError其他操作员方法(例如__radd__for __add__)将被尝试.
| 归档时间: |
|
| 查看次数: |
9264 次 |
| 最近记录: |