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

yipeiwu_com6年前Python基础

分享一下刚遇到的一个小问题,我有一段类似于这样的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实现批量改文件名称的方法。分享给大家供大家参考。具体分析如下: 发现python中提供了大量的模块函数,有时候一些系统操作在python中非常简单 下面的文件关...

python3.6 tkinter实现屏保小程序

本文实例为大家分享了python3.6 tkinter实现屏保小程序,供大家参考,具体内容如下 该小程序是在闲着没事的时候,随便写的,就当打发无聊了。 该程序是用python3.6写的,...

朴素贝叶斯Python实例及解析

本文实例为大家分享了Python朴素贝叶斯实例代码,供大家参考,具体内容如下 #-*- coding: utf-8 -*- #添加中文注释 from numpy import *...

手把手教你pycharm专业版安装破解教程(linux版)

手把手教你pycharm专业版安装破解教程(linux版)

1.首先到jetbrains下载专业版 https://www.jetbrains.com/pycharm/download/#section=linux 我这里下载的是pycharm-...

关于Pytorch的MNIST数据集的预处理详解

关于Pytorch的MNIST数据集的预处理详解

关于Pytorch的MNIST数据集的预处理详解 MNIST的准确率达到99.7% 用于MNIST的卷积神经网络(CNN)的实现,具有各种技术,例如数据增强,丢失,伪随机化等。 操作系统...