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 相关文章推荐
windows下python 3.6.4安装配置图文教程
Aug 21 Python
Python实现计算字符串中出现次数最多的字符示例
Jan 21 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
May 10 Python
mac系统下Redis安装和使用步骤详解
Jul 09 Python
python变量的存储原理详解
Jul 10 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
Feb 27 Python
Python调用OpenCV实现图像平滑代码实例
Jun 19 Python
keras实现theano和tensorflow训练的模型相互转换
Jun 19 Python
PyCharm上安装Package的实现(以pandas为例)
Sep 18 Python
详解pycharm自动import所需的库的操作方法
Nov 30 Python
Python爬虫之Selenium下拉框处理的实现
Dec 04 Python
Python数据可视化之用Matplotlib绘制常用图形
Jun 03 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 JSON中文乱码的解决方法详解
2013/06/06 PHP
PHP-Fcgi下PHP的执行时间设置方法
2013/08/02 PHP
PHP连接MySQL数据的操作要点
2015/03/20 PHP
php图片合成方法(多张图片合成一张)
2017/11/25 PHP
封装好的省市地区联动控件附下载
2007/08/13 Javascript
jquery中radio checked问题
2015/03/16 Javascript
easyui Droppable组件实现放置特效
2015/08/19 Javascript
jQuery实现简单的点赞效果
2020/05/29 Javascript
JavaScript中 ES6 generator数据类型详解
2016/08/11 Javascript
Jquery中.bind()、.live()、.delegate()和.on()之间的区别详解
2017/08/01 jQuery
node.js中fs文件系统目录操作与文件信息操作
2018/02/24 Javascript
JS中获取 DOM 元素的绝对位置实例详解
2018/04/23 Javascript
微信小程序时间标签和时间范围的联动效果
2019/02/15 Javascript
如何利用 JS 脚本实现网页全自动秒杀抢购功能
2020/10/12 Javascript
python django 访问静态文件出现404或500错误
2017/01/20 Python
基于python(urlparse)模板的使用方法总结
2017/10/13 Python
python装饰器简介---这一篇也许就够了(推荐)
2019/04/01 Python
python 随机生成10位数密码的实现代码
2019/06/27 Python
keras的siamese(孪生网络)实现案例
2020/06/12 Python
如何在Oracle中查看各个表、表空间占用空间的大小
2015/10/31 面试题
师范生实习个人的自我评价
2013/09/28 职场文书
新员工培训个人的自我评价
2013/10/09 职场文书
2013年保送生自荐信格式
2013/11/20 职场文书
小学教师国培感言
2014/02/08 职场文书
表决心的诗句大全
2014/03/11 职场文书
企业标语口号
2014/06/10 职场文书
先进单位事迹材料
2014/12/25 职场文书
给领导的感谢信范文
2015/01/23 职场文书
2015年科研工作总结范文
2015/05/13 职场文书
大学生实习证明
2015/06/16 职场文书
公司管理建议书
2015/09/14 职场文书
2016暑期师德培训心得体会
2016/01/09 职场文书
2016年小学感恩节活动总结
2016/04/01 职场文书
深入理解python协程
2021/06/15 Python
利用Python多线程实现图片下载器
2022/03/25 Python
微信小程序实现轮播图指示器
2022/06/25 Javascript