Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:为什么u getattr_u_u_u_u_u_u_u_u_u_u_u________________?_Python_Exception_Exception Handling_Python 3.x_Python 2.7 - Fatal编程技术网

Python:为什么u getattr_u_u_u_u_u_u_u_u_u_u_u________________?

Python:为什么u getattr_u_u_u_u_u_u_u_u_u_u_u________________?,python,exception,exception-handling,python-3.x,python-2.7,Python,Exception,Exception Handling,Python 3.x,Python 2.7,我正在与\uuu getattr\uuuu斗争。我有一个复杂的递归代码库,让异常传播很重要 class A(object): @property def a(self): raise AttributeError('lala') def __getattr__(self, name): print('attr: ', name) return 1 print(A().a) 结果: ('attr:

我正在与
\uuu getattr\uuuu
斗争。我有一个复杂的递归代码库,让异常传播很重要

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.\uu dict\uuu
。有什么想法吗?

我刚把代码改成

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
),
被称为“最后手段”


它没有明确的文档记录,但可以在“当属性查找未在通常位置找到属性时调用”下计算。当属性访问失败且出现AttributeError时,调用
\uuuuu getattr\uuuuu
。也许这就是为什么你认为它“捕捉”了错误。然而,事实并非如此,是Python的属性访问功能捕获了它们,然后调用
\uuu getattr\uu

但是
\uu getattr\uuu
本身不会捕获任何错误。如果在
\uuu getattr\uuuu>中引发AttributeError,则会得到无限递归。

表示:

如果该类还定义了
\uuuuuGetAttr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
,则后者将不会被调用,除非
\uuuuuuuuuuuuuuuuuuuuuuuuGetAttribute\uuuuu

我(通过inclusio unius est exclusio alterius)读到这句话,说属性访问调用
\uuuu getattr\uuuuu
如果
对象恰好引发
AttributeError
——无论是直接引发还是在描述符
\uuuuu get\uuuuu
(例如属性fget)内引发;请注意,应该“返回(计算的)属性值或引发
AttributeError
异常”


作为类比,运算符特殊方法可能会引发
未实现错误
,因此,将尝试使用其他运算符方法(例如
\uuuu radd\uuuu
for
\uu add\uuuu
)。

使用
\uu getattr\uuuuu
和同一类中的属性是危险的,因为它可能导致非常难以调试的错误

如果属性的getter抛出
AttributeError
,则
AttributeError
将被静默捕获,并调用
\uuu getattr\uuuu
。通常,这会导致
\uuuuu getattr\uuuuu
异常失败,但如果您非常不走运,则不会发生异常,您甚至无法轻松将问题追溯到
\uuuu getattr\uuuu

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

以下是您可以做的:

  • 避免在同一类中使用属性和
    \uuuuu getattr\uuuu
  • 添加一个
    尝试。。。除了
    block之外,所有属性getter都不是微不足道的
  • 保持属性获取程序简单,这样您就知道它们不会抛出
    AttributeError
  • 编写自己版本的
    @属性
    装饰器,它捕获
    属性错误
    ,并将其作为
    运行时错误
    重新抛出
  • 另见

    编辑:如果有人正在考虑解决方案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)
    
    class C(object):
    
        def __getattr__(self, name):
            ...
    
        @property
        @replace_attribute_error_with_runtime_error
        def complicated_property(self):
            ...
    
        ...
    

    然后在重写
    \uu getattr\uuuu
    的类中使用
    @property
    而不是
    @property
    ,当您将
    @property
    \uu getattr\uuuuu
    组合时,您将注定失败:

    class Paradise:
        pass
    
    class Earth:
        @property
        def life(self):
            print('Checking for paradise (just for fun)')
            return Paradise.breasts
        def __getattr__(self, item):
            print("sorry! {} does not exist in Earth".format(item))
    
    earth = Earth()
    try:
        print('Life in earth: ' + str(earth.life))
    except AttributeError as e:
        print('Exception found!: ' + str(e))
    
    提供以下输出:

    Checking for paradise (just for fun)
    sorry! life does not exist in Earth
    Life in earth: None
    
    当你真正的问题是打电话给天堂.乳房时


    \uuuu getattr\uuuu
    总是在出现
    AtributeError
    时调用。将忽略异常的内容

    可悲的是,这个问题没有解决方案,因为
    hasattr(地球,“生命”)
    将返回
    True
    (仅仅因为
    \uuuuu getattr\uuuuuuuu
    被定义),但仍然会通过属性“生命”实现,因为它不存在,而真正的根本问题是
    天堂


    我的部分解决方案包括在
    @property
    块中使用try-except,这些块已知会遇到
    属性错误
    异常。

    经常遇到这个问题,因为我实现了很多
    \uu getattr\uuuuu
    方法,并且有很多
    @property
    方法。我想出了一个装饰器来获得一条更有用的错误消息:

    def replace_attribute_error_with_runtime_error(f):
        @functools.wraps(f)
        def wrapped(*args, **kwargs):
            try:
                return f(*args, **kwargs)
            except AttributeError as e:
                # logging.exception(e)
                raise RuntimeError(
                    '{} failed with an AttributeError: {}'.format(f.__name__, e)
                )
        return wrapped
    
    然后像这样使用它:

    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)
    
    class C(object):
    
        def __getattr__(self, name):
            ...
    
        @property
        @replace_attribute_error_with_runtime_error
        def complicated_property(self):
            ...
    
        ...
    
    基础异常的错误消息将包括其实例引发基础
    AttributeError
    的类的名称。
    如果愿意,您也可以将其记录下来。

    建议使用什么方法?不使用属性或使用
    \uuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,捕获
    AttributeError
    。我无法理解您为什么要在属性中显式提升
    AttributeError
    。或者除了
    (get | set)attr[ibute]\uuuu
    方法以外的任何地方,真的。显式引发AttributeError不是这件事的意义。。。问题是,我有一个复杂的程序,其中引发了一个AttributeError(由于编程错误),但我不知道在哪里,因为
    \uuu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>对我隐藏了它。@glglglglglgl:我不像引发了
    AttributeError
    ,我只是犯了编程。最后,我什么也看不到,因为它被
    \uuuuGetAttr\uuuuuuuu
    捕获了。我想说文档的失败之处在于它声明
    属性错误可以在
    \uuuuuu get\uuuuuuuu
    中提出(这是您在这里有效地做的),但没有解释什么是ef