property的AttributeError的传播问题

栏目: IT技术 · 发布时间: 4年前

内容简介:去年我写过一篇今天又遇到了一个 AttributeError 向上传播的问题 (Python 2),一起来看看先上代码:

前言

去年我写过一篇 你用对 hasattr 了嘛? 介绍过被 property 装饰的方法内部抛错会引起 hasattr 的结果为 False。

今天又遇到了一个 AttributeError 向上传播的问题 (Python 2),一起来看看

问题

先上代码:

In : class T(object):
...:     @property
...:     def name(self):
...:         print(self.missing_attribute)
...:         return 42
...:     def __getattr__(self, name):
...:         raise AttributeError(name)
...:

In : t = T()

In : t.name
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-afc812d51b9a> in <module>()
----> 1 t.name

<ipython-input-4-a0ba2d3a6446> in __getattr__(self, name)
      5         return 42
      6     def __getattr__(self, name):
----> 7         raise AttributeError(name)
      8

AttributeError: name

In : [k for k in dir(t) if not k.startswith('_')]
Out: ['name']

这个例子需要细品,明明有 name 这个属性却抛出了 AttributeError。分析一下:

  1. 通过 __getattr__ 定制属性查找的逻辑,当用户试图获取一个不存在的属性时就会抛 AttributeError 错误
  2. 获取 name 属性的逻辑中包含 print (self.missing_attribute) 这句,由于没有这个属性会执行到 __getattr__ 然后抛 AttributeError

一看到这个违背常理的错误,我就想起来 hasattr 的那个问题,觉得应该是类似的原因。网上一搜果然之前有人已经给 CPython 提过 issue 了,具体可以看延伸阅读链接。总结一下,这个问题的出现需要有 2 个点都满足:

__getattr__

相当于方法中的 AttributeError 没有被处理,传播到 __getattr__ 了。再看一个例子:

In : class T(object):
...:     @property
...:     def name(self):
...:         raise AttributeError('This message will not be displayed!')
...:         return 'Hello'
...:     def __getattr__(self, name):
...:         return 0
...:

In : t = T()

In : t.name
Out: 0

一旦 name 方法中由于各种原因会抛 AttributeError 错误 (别的错误不行),就会走 __getattr__ 里面的逻辑。

怎么解决?

这不是一个 BUG,但是代码编写者不能规避这类问题,怎么办呢?最简单的办法是使用 __getattribute__ 替代 __getattr__ ,演示一下:

In : class T(object):
...:     @property
...:     def name(self):
...:         raise AttributeError('This message will not be displayed!')
...:         return 'Hello'
...:
...:     def __getattribute__(self, name):
...:         try:
...:             return super(T, self).__getattribute__(name)
...:         except AttributeError as e:
...:             raise e
...:

In : t = T()

In : t.name
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-28-afc812d51b9a> in <module>()
----> 1 t.name

<ipython-input-26-a27dd1330f44> in __getattribute__(self, name)
      9             return super(T, self).__getattribute__(name)
     10         except AttributeError as e:
---> 11             raise e
     12

AttributeError: This message will not be displayed!

In : class T(object):
...:     @property
...:     def name(self):
...:         print(self.missing_attribute)
...:         return 42
...:     def __getattribute__(self, name):
...:         try:
...:             return super(T, self).__getattribute__(name)
...:         except AttributeError as e:
...:             raise e
...:

In : t = T()

In : t.name
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-31-afc812d51b9a> in <module>()
----> 1 t.name

<ipython-input-29-da47b1a1e093> in __getattribute__(self, name)
      8             return super(T, self).__getattribute__(name)
      9         except AttributeError as e:
---> 10             raise e
     11

AttributeError: 'T' object has no attribute 'missing_attribute'

就是这样~

延伸阅读

  1. https://bugs.python.org/issue24983

以上所述就是小编给大家介绍的《property的AttributeError的传播问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

当下的启蒙

当下的启蒙

[美] 史迪芬·平克 / 侯新智、欧阳明亮、魏薇 / 浙江人民出版社 / 2018-12 / 159.90

[编辑推荐] ● 比尔•盖茨最喜爱的一本书。理查德·道金斯心中的诺贝尔文学奖作品。尤瓦尔•赫拉利2018年最爱的书之一。 ● 当代最伟大思想家史蒂芬·平克全面超越自我的巅峰之作,一部关于人类进步的英雄史诗。 ●《当下的启蒙》用数据和事实揭示出世界的真相:不是黑暗,而是光明;不是丧,而是燃;我们没有退步,而是一直在进步,还将继续进步。用这本书点燃生活的勇气,亲手创造更美好的未来。 ......一起来看看 《当下的启蒙》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具