我编写了这个描述符类,当我尝试在不同的类中使用它时,它给了我这个错误:
RecursionError: maximum recursion depth exceeded
class x:
def __init__(...):
...
def __set_name__(self, _, name):
self.internal_name = name
def __get__(self, instance, _):
if instance is None:
return
else:
return getattr(instance, self.internal_name)
def __set__(self, instance, value):
if instance is None:
return
else:
setattr(instance, self.internal_name, value)
我发现通过将我的
__set_name__
方法更改为此,我不再遇到此问题:
def __set_name__(self, _, name):
self.internal_name = f'_{name}'
但我不确定为什么会这样。您能帮忙解释一下为什么我需要确保该名称与我从
__set_name__
返回的值不同吗
这是因为您正在打电话:
getattr(instance, self.internal_name)
由于
self.internal_name
与正在访问的描述符实例的名称具有相同的值,因此 getattr
会调用相同实例的同一描述符实例的 __get__
,从而导致无限递归。同样的情况也适用于您拨打 setattr
。
通过将
self.internal_name
命名为与描述符实例的名称不同,getattr(instance, self.internal_name)
不再引用描述符实例的值,并且会正确回退到在实例的成员字典中查找属性名称以及在MRO。