title: Why super(SubPerson, SubPerson).name.__set__(self, value) Calls a GETTER in a Descriptor. (Not a Setter)
body: <p>I am examining how descriptors work and their extension by a child class. I noticed then when I use Descriptor, in comparison with normal Parent-Child extending getters/setters - in Descriptor version the:</p>
  <pre><code>super(SubPerson, SubPerson).name.__set__(self, value)  
  </code></pre>
  <p>calls the GETTER, not a Setter.</p>
  <p>Better to explain by example, see both versions below. Commented on the specified line with super(). Output commented below each part. The question is why getter is called? Thanks.</p>
  <p>Descriptor:</p>
  <pre><code># Code where super(SubPerson, SubPerson).name.__set__(self, value) CALLS GETTER!
  
  # A descriptor - Checking if Attribute is of type String
  class String:
      def __init__(self, name):
          print(&quot;Descriptor__init__&quot;)
          self.name = name
  
      def __get__(self, instance, cls):
          print(&quot;Descriptor__get__&quot;)
          if instance is None:
              return self
          return instance.__dict__[self.name]
  
      def __set__(self, instance, value):
          print(&quot;Descriptor__set__&quot;)
          if not isinstance(value, str):
              raise TypeError('Expected a string')
          instance.__dict__[self.name] = value
  
  # A class with a descriptor
  class Person:
      name = String('name') # Class Variable - for a Descriptor
      def __init__(self, name):
          self.name = name
  
  # Here we extend the Descriptor functionality with a property
  class SubPerson(Person):
      @property
      def name(self):
          # print('Getting name') # use case
          print(&quot;Extended__get__&quot;) # debug
          return super().name
  
      @name.setter
      def name(self, value):
          # print('Setting name to', value) # use case
          print(&quot;Extended__set__&quot;) # debug
          super(SubPerson, SubPerson).name.__set__(self, value) # THIS CALLS THE &quot;GETTER&quot; OF A PARENT (DESCRIPTOR)
  
      @name.deleter
      def name(self):
          print('Deleting name') # use case
          print(&quot;Extended__delete__&quot;) # debug
          super(SubPerson, SubPerson).name.__delete__(self)
  
  
  
  if __name__ == '__main__':
      b = SubPerson(&quot;Retko&quot;)
  
      # Descriptor__init__
      # Extended__set__
      # Descriptor__get__
      # Descriptor__set__
  </code></pre>
  <p>No Descriptor:</p>
  <pre><code># Code where super(SubPerson, SubPerson).name.__set__(self, value) CALLS SETTER!
  
  class Person:
      def __init__(self, name):
          print(&quot;Parent __init__&quot;)
          self.name = name # this will call the Setter
  
      # Getter function
      @property
      def name(self):
          print(&quot;Parents Getter&quot;)
          return self._name
  
      # Setter function
      @name.setter
      def name(self, value):
          print(&quot;Parent_Setter&quot;)
          if not isinstance(value, str):
              raise TypeError('Expected a string')
          self._name = value
  
      @name.deleter
      def name(self):
          raise AttributeError(&quot;Can't delete attribute&quot;)
  
  class SubPerson(Person):
      @property
      def name(self):
          # print('Getting name')
          print(&quot;Extended__get__&quot;) # debug
          return super().name
  
      @name.setter
      def name(self, value):
          # print('Setting name to', value)
          print(&quot;Extended__set__&quot;) # debug
          super(SubPerson, SubPerson).name.__set__(self, value) # THIS CALLS THE &quot;SETTER&quot; OF A PARENT
  
      @name.deleter
      def name(self):
          # print('Deleting name')
          print(&quot;Extended__delete__&quot;) # debug
          super(SubPerson, SubPerson).name.__delete__(self)
  
  
  if __name__ == '__main__':
  
      s = SubPerson ( 'Guido' )
      # Parent __init__
      # Extended__set__
      # Parent_Setter
  
  </code></pre>
  <p>Thanks.</p>