python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享
2014-07-09 00:00
1091 查看
分享一下刚遇到的一个小问题,我有一段类似于这样的python代码:
运行后可以得到正确的结果
但是注意,如果把
这行的注释去掉的话,即在_value方法里面抛出AttributeError异常,事情就会变得有些奇怪。程序运行的时候并不会抛出异常,而是会进入一个无限递归:
通过多方查找后发现是property装饰器的问题,property实际上是一个descriptor。在python doc中可以发现这样的文字:
这样当用户访问._value时,抛出了AttributeError从而调用了__getattr__方法去尝试获取。这样程序就变成了无限递归。
这个问题看上去不复杂,但是当你的_value方法是比较隐晦的抛出AttributeError的话,调试起来就会比较困难了。
# 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的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享
- 用 Python 的 Descriptor 特性解决一个变态的问题
- jackson java转json hibernate 造成的堆栈溢出 无限递归问题
- 分享脚本,同一个问题,php,python,shell的写法
- 分享一个连接,python扩展包下载地址分享包括numpy,scipy等,解决了win8系统不能使用这些扩展包的问题!
- 用 Python 的 Descriptor 特性解决一个变态的问题
- jackson java转json hibernate懒加载造成的无限递归问题
- Qt creator工程项目移植时因环境变换造成qmake错误的解决方案 1.问题描述:移植从他机上的qt工程项目,打开时提示: Qt Creator找到了一个由其他开发环境创建的设置文件,或许
- 用 Python 的 Descriptor 特性解决一个变态的问题
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(3) 最大子序列和问题
- 用 Python 的 Descriptor 特性解决一个变态的问题
- 小问题,对递归重复调用的改进,一起来分享
- 帮人解决一个小问题:QQ空间登录时脚本错误造成无法登入
- Python Django还是RoR,这是一个问题
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(2) IntCell类
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(1) f(x) = 2f(x-1) + x^2
- 史上最难的初等几何问题?分享一个参考答案
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(6)高效率的幂运算
- 一个关于Python的类覆盖的问题
- Python Django还是RoR,这是一个问题