首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >AttributeErrors :为什么__getattr__要追赶Python?

AttributeErrors :为什么__getattr__要追赶Python?
EN

Stack Overflow用户
提问于 2012-06-20 17:48:45
回答 6查看 11.9K关注 0票数 14

我和__getattr__很纠结。我有一个复杂的递归代码库,其中让异常传播是很重要的。

代码语言:javascript
运行
复制
class A(object):
    @property
    def a(self):
        raise AttributeError('lala')

    def __getattr__(self, name):     
        print('attr: ', name)
        return 1      

print(A().a)

结果如下:

代码语言:javascript
运行
复制
('attr: ', 'a')
1

为什么会有这样的行为?为什么没有抛出异常?这种行为没有文档记录(__getattr__ documentation)。getattr()可以直接使用A.__dict__。有什么想法吗?

EN

回答 6

Stack Overflow用户

发布于 2012-06-20 18:08:22

我刚把代码改成

代码语言:javascript
运行
复制
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)

而且,正如我们所看到的,属性确实是最先尝试的。但由于它声称不存在(通过引发AttributeError),__getattr__()被称为“最后的手段”。

它没有清楚地记录下来,但可以被计入“当属性查找在通常的位置没有找到属性时调用”。

票数 9
EN

Stack Overflow用户

发布于 2014-06-17 18:03:51

在同一个类中使用__getattr__和属性是危险的,因为它可能导致很难调试的错误。

如果一个属性的getter抛出AttributeError,那么这个AttributeError就会被静默捕获,然后__getattr__就会被调用。通常,这会导致__getattr__失败并引发异常,但如果您非常不幸,它就不会失败,而且您甚至不能轻松地将问题追溯到__getattr__

除非你的属性getter是微不足道的,否则你永远不能100%确定它不会抛出AttributeError。异常可能会抛出多个级别。

下面是你可以做的:

  1. 避免在同一个类中使用属性和代码。
  2. 向所有不是微不足道的属性getter添加try ... except
  3. 使属性getter保持简单,这样您就知道他们不会抛出您自己版本的@property装饰器,该装饰器会捕获<代码>D19__getattr__ >并将其作为代码重新抛出

另请参阅http://blog.devork.be/2011/06/using-getattr-and-property_17.html

编辑:如果有人正在考虑解决方案4(我不推荐),可以这样做:

代码语言:javascript
运行
复制
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)

然后在覆盖__getattr__的类中使用@property_而不是@property

票数 9
EN

Stack Overflow用户

发布于 2012-06-20 18:46:11

__getattribute__ documentation说:

如果该类还定义了__getattr__(),则不会调用后者,除非__getattribute__()显式调用它或引发AttributeError

我读到这篇文章(由inclusio unius est exclusio alterius)说,如果object.__getattribute__ (“被无条件地调用来实现属性访问”)碰巧引发AttributeError -无论是直接还是在描述符__get__ (例如属性fget)中,属性访问调用__getattr__;请注意__get__应该“返回(计算的)属性值或引发AttributeError异常”。

作为类比,运算符特殊方法可以引发NotImplementedError,从而尝试其他运算符方法(例如,__add____radd__ )。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11116896

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档