2

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?

triccare
  • 145
  • 1
  • 9
  • If expected, is there a particular reason for the discrepancy: The descriptor.__get__ is invoked on reference. Why would descriptor.__set__ not be? Or is this a "just move along" situation? – triccare Jul 30 '19 at 14:17
  • 2
    I effectively re-asked this, together with some additional diving into the CPython implementation, and got a lot of helpful feedback: [Why does setting a descriptor on a class overwrite the descriptor?](https://stackoverflow.com/questions/58420173/why-does-setting-a-descriptor-on-a-class-overwrite-the-descriptor) – Michael Carilli Oct 16 '19 at 21:42

0 Answers0