Question: Class attributes apparently do not access the descriptors' __set__
method. Is this expected or is there some issue?
Below code demonstrates the problem. The code is pulled straight from the Python documentation.
class RevealAccess:
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
print('Retrieving', self.name)
print(f'obj = {obj}')
print(f'objtype = {objtype}')
return self.val
def __set__(self, obj, val):
print('Updating', self.name)
self.val = val
class MyReveal:
x = RevealAccess(10, 'var "x"')
Creating an instance behaves as expected:
>>> mr = MyReveal()
>>> mr.x
Retrieving var "x"
obj = <__main__.MyReveal object at 0x139246eb8>
objtype = <class '__main__.MyReveal'>
>>> mr.x = 'set mr.x'
Updating var "x"
Retrieving var "x"
obj = <__main__.MyReveal object at 0x139246eb8>
objtype = <class '__main__.MyReveal'>
When using directly on the class attribute, the __get__
behaves as expected:
>>> MyReveal.x
Retrieving var "x"
obj = None
objtype = <class '__main__.MyReveal'>
MyReveal.x=set mr.x
However, when trying to set, the __set__
seems to be ignored and the attribute is just written over, losing the descriptor:
>>> MyReveal.x = 'set MyReveal.x'
<no output>
>>> MyReveal.x
'set MyReveal.x'
>>> mr.x
'set MyReveal.x'
As seen, the diagnostics from the descriptor are gone, leaving the value of the x
attribute just the bare str.
Is this expected behavior? Or, more likely, what am I doing wrong? Or, a bug?