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处理json数据中的中文
Mar 06 Python
举例讲解Python中的算数运算符的用法
May 13 Python
python类的方法属性与方法属性的动态绑定代码详解
Dec 27 Python
python matlibplot绘制多条曲线图
Feb 19 Python
python3中property使用方法详解
Apr 23 Python
python turtle库画一个方格和圆实例
Jun 27 Python
Django基础知识 web框架的本质详解
Jul 18 Python
python3实现微型的web服务器
Sep 03 Python
pytorch逐元素比较tensor大小实例
Jan 03 Python
Python requests模块cookie实例解析
Apr 14 Python
如何实现更换Jupyter Notebook内核Python版本
May 18 Python
Python SMTP配置参数并发送邮件
Jun 16 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
ThinkPHP采用模块和操作分析
2011/04/18 PHP
php实现的一个简单json rpc框架实例
2015/03/30 PHP
PHP网络操作函数汇总
2015/05/18 PHP
PHP中你应该知道的require()文件包含的正确用法
2015/06/12 PHP
一些有用的JavaScript和jQuery的片段分享
2011/08/23 Javascript
input 输入框获得/失去焦点时隐藏/显示文字(jquery版)
2013/04/02 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
在JavaScript中判断整型的N种方法示例介绍
2014/06/18 Javascript
js实现用户离开页面前提示是否离开此页面的方法(包括浏览器按钮事件)
2015/07/18 Javascript
如何用angularjs制作一个完整的表格
2016/01/21 Javascript
jQuery实现点击水纹波动动画
2016/04/10 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
深入解读Node.js中的koa源码
2019/06/17 Javascript
简单了解微信小程序 e.target与e.currentTarget的不同
2019/09/27 Javascript
小程序api实现promise封装过程解析
2019/11/21 Javascript
vue 动态组件(component :is) 和 dom元素限制(is)用法说明
2020/09/04 Javascript
[01:37]DOTA2超级联赛专访ChuaN 传奇般的电竞之路
2013/06/19 DOTA
[01:02:45]完美世界DOTA2联赛 LBZS vs Forest 第三场 11.07
2020/11/09 DOTA
Python计算程序运行时间的方法
2014/12/13 Python
python批量提取word内信息
2015/08/09 Python
Python时间戳使用和相互转换详解
2017/12/11 Python
基于python log取对数详解
2018/06/08 Python
Python读取英文文件并记录每个单词出现次数后降序输出示例
2018/06/28 Python
Python获取当前脚本文件夹(Script)的绝对路径方法代码
2019/08/27 Python
python 一维二维插值实例
2020/04/22 Python
Python流程控制语句的深入讲解
2020/06/15 Python
荷兰网上买鞋:MooieSchoenen.nl
2017/09/12 全球购物
新西兰领先的内衣店:Bendon Lingerie新西兰
2018/07/11 全球购物
2014学习全国两会精神心得体会2000字
2014/03/11 职场文书
学前班评语大全
2014/05/04 职场文书
促销活动总结模板
2014/07/01 职场文书
社会学专业求职信
2014/07/17 职场文书
三严三实·严以用权心得体会
2016/01/12 职场文书
低端且暴利的线上线下创业项目分享
2019/09/03 职场文书
2019年励志签名:致拼搏路上的自己
2019/10/11 职场文书
MySQL三种方式实现递归查询
2022/04/18 MySQL