I have been playing with my code and I ended up with this:
class TestProperty:
def __init__(self,func):
self.func = func
def __set__(self,instance,value):
setattr(instance,self.func.__name__,value)
def __get__(self,instance,cls):
if instance is None:
return self
else:
return getattr(instance,self.func.__name__)
class John(object):
def __init__(self):
pass
@TestProperty
def TestProp(self):
print('This line won\'t be printed')
p = John()
p.TestProp = 99
print(p.TestProp)
I'm trying to understand the behavior when creating a class descriptor and using them on methods instead of attributes. I am having a hard time understanding what's going on underneath and It would be really nice if someone can shed some light on me how did this end up as recursive error?
My initial guess is something like this:
__set__
or __get__
depending on how we accessed it. Can anyone explain to me in great detail how did this happen and how do I resolve this?
The code provided serves no purpose other than understanding the behavior of class descriptor.
Don't use getattr()
and setattr()
; you are triggering the descriptor again there! The descriptor handles all access to the TestProp
name, using setattr()
and getattr()
just goes through the same path as p.TestProp
would.
Set the attribute value directly in the instance.__dict__
:
def __get__(self,instance,cls):
if instance is None:
return self
try:
return instance.__dict__[self.func.__name__]
except KeyError:
raise AttributeError(self.func.__name__)
def __set__(self,instance,value):
instance.__dict__[self.func.__name__] = value
This works because you have a data descriptor ; a data descriptor takes precedence over instance attributes. Access to p.TestProp
continues to use the descriptor object on the class even though the name 'TestProp'
exists in instance __dict__
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.