时间:2021-05-22
分享一下刚遇到的一个小问题,我有一段类似于这样的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的话,调试起来就会比较困难了。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
最近在阅读Python微型Web框架Bottle的源码,发现了Bottle中有一个既是装饰器类又是描述符的有趣实现。刚好这两个点是Python比较的难理解,又混
描述符(descriptor)是实现了__get__、__set__、__del__方法的类,进一步可以细分为两类:数据描述符:实现了__get__和__set
描述符(Descriptors)是Python语言中一个深奥但却重要的一部分。它们广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具
@property作用:python的@property是python的一种装饰器,是用来修饰方法的。我们可以使用@property装饰器来创建只读属性,@pr
@property作用:python的@property是python的一种装饰器,是用来修饰方法的。我们可以使用@property装饰器来创建只读属性,@pr