当前位置: 首页 > 编程笔记 >

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

艾志尚
2023-03-14
本文向大家介绍python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享,包括了python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享的使用技巧和注意事项,需要的朋友参考一下

分享一下刚遇到的一个小问题,我有一段类似于这样的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.

这样当html" target="_blank">用户访问._value时,抛出了AttributeError从而调用了__getattr__方法去尝试获取。这样程序就变成了无限递归。

这个问题看上去不复杂,但是当你的_value方法是比较隐晦的抛出AttributeError的话,调试起来就会比较困难了。

 类似资料:
  • 本文向大家介绍解密Python中的描述符(descriptor),包括了解密Python中的描述符(descriptor)的使用技巧和注意事项,需要的朋友参考一下 Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解。这些特性包括列表/集合/字典推导式,属性(property)、以及装饰器(decorator)。对于大部分特性来说,这些“中级”的语言特性有着完善的文档,并且易于学习。

  • 本文向大家介绍Python描述器descriptor详解,包括了Python描述器descriptor详解的使用技巧和注意事项,需要的朋友参考一下 前面说了descriptor,这个东西其实和Java的setter,getter有点像。但这个descriptor和上文中我们开始提到的函数方法这些东西有什么关系呢? 所有的函数都可以是descriptor,因为它有__get__方法。  注意,函数对

  • 本文向大家介绍Python描述符descriptor使用原理解析,包括了Python描述符descriptor使用原理解析的使用技巧和注意事项,需要的朋友参考一下 描述符(descriptor)是实现了__get__、__set__、__del__方法的类,进一步可以细分为两类: 数据描述符:实现了__get__和__set__ 非数据描述符:没有实现__set__ 描述符在类的属性调用中起着很重

  • 问题内容: 我想了解内置功能的工作原理。令我感到困惑的是,它还可以用作装饰器,但是仅当用作内置函数时才接受参数,而不能用作装饰器。 这个例子来自文档: 的论点是和文档字符串。 在下面的代码中用作装饰器。它的对象是函数,但是在上面的代码中,参数中没有对象函数的位置。 并且,和装饰器是如何创建的?我很困惑。 问题答案: 该函数返回一个特殊的描述符对象: 正是这种对象有额外的方法: 这些充当装饰过。他们

  • 本文向大家介绍Python @property装饰器原理解析,包括了Python @property装饰器原理解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Python @property装饰器原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.通过@property装饰器,可以直接通过方法名来访问方法,不需要在方法名后

  • 中断描述符表把每个中断或异常编号和一个指向中断处理事件服务程序的描述符联系起来。同GDT和LDT一样,IDT是一个8-字节的描述符数组。和GDT、LDT不同的是,IDT的第一项可以包含一个描述符。为了形成一个在IDT内的索引,处理器把中断、异常标识号乘以8以后来做为IDT的索引。因为只有256个编号,IDT不必包含超过256个描述符。它可以包含比256更少的项,只是那些需要使用的中断、异常的项。