I have this descriptor class that I wrote that gives me this error when I try to use it in a different class:
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)
I found that by changing my __set_name__
method to this I no longer get this issue:
def __set_name__(self, _, name):
self.internal_name = f'_{name}'
But I am unsure as to why this is the case. Could you help explain why I need to make sure the name is different from the value I get back from __set_name__
This is because you're calling:
getattr(instance, self.internal_name)
with self.internal_name
having the same value as the name of the descriptor instance being accessed, so getattr
invokes another call to __get__
of the same descriptor instance with the same instance, which again calls getattr(instance, self.internal_name)
, resulting in infinite recursion. The same situation applies to your call to setattr
.
By naming self.internal_name
differently from the name of the descriptor instance, getattr(instance, self.internal_name)
no longer refers to the descriptor instance for a value and would properly fallback to looking up the the attribute name in the members dict of the instance and the types in the MRO.