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实现2048小游戏
Mar 30 Python
python爬取w3shcool的JQuery课程并且保存到本地
Apr 06 Python
Python分治法定义与应用实例详解
Jul 28 Python
python3 发送任意文件邮件的实例
Jan 23 Python
Django处理文件上传File Uploads的实例
May 28 Python
Python中list查询及所需时间计算操作示例
Jun 21 Python
PyCharm代码提示忽略大小写设置方法
Oct 28 Python
详解python函数的闭包问题(内部函数与外部函数详述)
May 17 Python
python绘制已知点的坐标的直线实例
Jul 04 Python
Python 获取指定文件夹下的目录和文件的实现
Aug 30 Python
解决pytorch DataLoader num_workers出现的问题
Jan 14 Python
python批量提取图片信息并保存的实现
Feb 05 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 编程请选择正确的文本编辑软件
2006/12/21 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
2015/03/19 PHP
基于laravel制作APP接口(API)
2016/03/15 PHP
laravel框架数据库操作、查询构建器、Eloquent ORM操作实例分析
2019/12/20 PHP
通过PHP实现获取访问用户IP
2020/05/09 PHP
javascript new 需不需要继续使用
2009/07/02 Javascript
Extjs学习笔记之三 extjs form更多的表单项
2010/01/07 Javascript
理解Javascript_08_函数对象
2010/10/15 Javascript
javascript学习笔记(九) js对象 设计模式
2012/06/19 Javascript
JavaScript格式化日期时间的方法和自定义格式化函数示例
2014/04/04 Javascript
深入理解javascript中的立即执行函数(function(){…})()
2014/06/12 Javascript
简介JavaScript中的getSeconds()方法的使用
2015/06/10 Javascript
jquery+json实现动态商品内容展示的方法
2016/01/14 Javascript
jQuery实现的跨容器无缝拖动效果代码
2016/06/21 Javascript
jQuery根据name属性进行查找的用法分析
2016/06/23 Javascript
详细探究ES6之Proxy代理
2016/07/22 Javascript
yarn与npm的命令行小结
2016/10/20 Javascript
JS处理一些简单计算题
2018/02/24 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
2018/07/10 Javascript
微信小程序开发之tabbar图标和颜色的实现
2018/10/17 Javascript
微信小程序实现留言板(Storage)
2018/11/02 Javascript
详谈Vue.js框架下main.js,App.vue,page/index.vue之间的区别
2020/08/12 Javascript
[01:02:46]VGJ.S vs NB 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python 逐行分割大txt文件的方法
2017/10/10 Python
python logging日志模块以及多进程日志详解
2018/04/18 Python
python3爬虫之设计签名小程序
2018/06/19 Python
2020新版本pycharm+anaconda+opencv+pyqt环境配置学习笔记,亲测可用
2020/03/24 Python
程序运行正确, 但退出时却"core dump"了,怎么回事
2014/02/19 面试题
大学生求职简历的自我评价范文
2013/10/12 职场文书
《桂林山水》教学反思
2014/02/08 职场文书
经济担保书范文
2014/04/02 职场文书
党员对照检查材料思想汇报(党的群众路线)
2014/09/24 职场文书
销售会议开幕词
2015/01/28 职场文书
大学生学年个人总结
2015/02/15 职场文书
放假通知怎么写
2015/08/18 职场文书
MySQL的索引你了解吗
2022/03/13 MySQL