python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享


Posted in Python onJuly 09, 2014

分享一下刚遇到的一个小问题,我有一段类似于这样的python代码:

# coding: utf-8
class A(object):
    @property

    def _value(self):

#        raise AttributeError("test")

        return {"v": "This is a test."}
    def __getattr__(self, key):

        print "__getattr__:", key

        return self._value[key]
if __name__ == '__main__':

    a = A()

    print a.v

运行后可以得到正确的结果
__getattr__: v

This is a test.

但是注意,如果把
#        raise AttributeError("test")

这行的注释去掉的话,即在_value方法里面抛出AttributeError异常,事情就会变得有些奇怪。程序运行的时候并不会抛出异常,而是会进入一个无限递归:

File "attr_test.py", line 12, in __getattr__

    return self._value[key]

  File "attr_test.py", line 12, in __getattr__

    return self._value[key]

RuntimeError: maximum recursion depth exceeded while calling a Python object

通过多方查找后发现是property装饰器的问题,property实际上是一个descriptor。在python doc中可以发现这样的文字:

object.__get__(self, instance, owner)
Called to get the attribute of the owner class (class attribute access) or of an instance of that class (instance attribute access). owner is always the owner class, while instance is the instance that the attribute was accessed through, or None when the attribute is accessed through the owner. This method should return the (computed) attribute value or raise an AttributeError exception.

这样当用户访问._value时,抛出了AttributeError从而调用了__getattr__方法去尝试获取。这样程序就变成了无限递归。

这个问题看上去不复杂,但是当你的_value方法是比较隐晦的抛出AttributeError的话,调试起来就会比较困难了。

Python 相关文章推荐
用Python程序抓取网页的HTML信息的一个小实例
May 02 Python
python实现按任意键继续执行程序
Dec 30 Python
Python基于list的append和pop方法实现堆栈与队列功能示例
Jul 24 Python
详解tensorflow载入数据的三种方式
Apr 24 Python
使用python实现http及ftp服务进行数据传输的方法
Oct 26 Python
Python实现的文轩网爬虫完整示例
May 16 Python
Django上使用数据可视化利器Bokeh解析
Jul 31 Python
python实现爬虫抓取小说功能示例【抓取金庸小说】
Aug 09 Python
Python matplotlib画曲线例题解析
Feb 07 Python
如何在Django中使用聚合的实现示例
Mar 23 Python
python实现发送带附件的邮件代码分享
Sep 22 Python
Python+Appium实现自动抢微信红包
May 21 Python
Python中__init__和__new__的区别详解
Jul 09 #Python
Python中使用logging模块代替print(logging简明指南)
Jul 09 #Python
Python中的魔法方法深入理解
Jul 09 #Python
gearman的安装启动及python API使用实例
Jul 08 #Python
python实现跨文件全局变量的方法
Jul 07 #Python
Python中的并发编程实例
Jul 07 #Python
Python编程语言的35个与众不同之处(语言特征和使用技巧)
Jul 07 #Python
You might like
PHP 使用MySQL管理Session的回调函数详解
2013/06/21 PHP
php小经验:解析preg_match与preg_match_all 函数
2013/06/29 PHP
typecho插件编写教程(一):Hello World
2015/05/28 PHP
yii2中的rules 自定义验证规则详解
2016/04/19 PHP
PHP创建文件及写入数据(覆盖写入,追加写入)的方法详解
2019/02/15 PHP
javascript的trim,ltrim,rtrim自定义函数
2008/09/21 Javascript
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
jquery 经典动画菜单效果代码
2010/01/26 Javascript
jQuery.Validate 使用笔记(jQuery Validation范例 )
2010/06/25 Javascript
初窥JQuery(二)事件机制(2)
2010/12/06 Javascript
jquery 面包屑导航 具体实现
2013/06/05 Javascript
jQuery获取iframe的document对象的方法
2014/10/10 Javascript
jQuery实现的图片分组切换焦点图插件
2015/01/06 Javascript
js实现搜索框关键字智能匹配代码
2020/03/26 Javascript
Bootstrap开发实战之第一次接触Bootstrap
2016/06/02 Javascript
微信小程序 JS动态修改样式的实现代码
2017/02/10 Javascript
ie下js不执行的几种可能
2017/02/28 Javascript
使用gulp搭建本地服务器并实现模拟ajax
2017/04/05 Javascript
JS实现针对给定时间的倒计时功能示例
2017/04/11 Javascript
vue-resource:jsonp请求百度搜索的接口示例
2019/11/09 Javascript
微信小程序实现发微博功能的示例代码
2020/06/24 Javascript
VSCode插件安装完成后的配置(常用配置)
2020/08/24 Javascript
JavaScript Array.flat()函数用法解析
2020/09/02 Javascript
使用Python下的XSLT API进行web开发的简单教程
2015/04/15 Python
python-opencv颜色提取分割方法
2018/12/08 Python
python接口自动化(十六)--参数关联接口后传(详解)
2019/04/16 Python
使用 Python 在京东上抢口罩的思路详解
2020/02/27 Python
python打包生成so文件的实现
2020/10/30 Python
Eton丹麦官网:精美的男式衬衫
2020/05/27 全球购物
专科毕业生学习生活的自我评价
2013/10/26 职场文书
简历上的自我评价
2014/02/03 职场文书
四风存在的原因分析
2014/02/11 职场文书
岗位职责说明书
2014/05/07 职场文书
妇女干部培训方案
2014/05/12 职场文书
2014年社区党建工作总结
2014/11/11 职场文书
法院答辩状格式
2015/05/22 职场文书