Not understood error with __set_name__ in a descriptor class

Dieter Maurer dieter at handshake.de
Sun Apr 19 12:37:18 EDT 2020


ast wrote at 2020-4-19 17:14 +0200:
>Le 19/04/2020 à 17:06, ast a écrit :
>I understood where the problem is.
>
>Once __get__ is defined, it is used to read self._name in method
>__set_name__ and it is not défined yet. That's why I have
>an error "'NoneType' object is not callable"
>Thats a nice bug.

What about the following (more straight forward) interpretation:

  In your test class, you call `my_property` without parameters.
  This means that the instance has `fget is None` and (therefore)
  `__get__` will raise the exception.

As you have already found out, `Test.celsius` invokes `__get__`
(with `instance is None`) and you get the observed error.

> ...
>> This code is working well: (I am using python 3.6.3)
>>
>> --------------------------------------------------------------------
>> class my_property:
>>      def __init__(self, fget=None, fset=None, fdel=None):
>>          self.fget = fget
>>          self.fset = fset
>>          self.fdel = fdel
>>      def __set_name__(self, owner, name):
>>          self._name = name
>>          print("Inside __set_name__ method:  ", self._name)
>>
>> ##    def __get__(self, instance, owner):
>> ##        return self.fget(instance)
>>
>>
>> class Test:
>>      celsius = my_property()
>>
>> print("Outside __set_name__ method: ", Test.celsius._name)
>>
>>
>> Here is the output:
>>
>> ========= RESTART: C:/Users/jm/Desktop/python/my_property.py =========
>> Inside __set_name__ method:   celsius
>> Outside __set_name__ method:  celsius
>> --------------------------------------------------------------------
>>
>> And this one doesn't. (I just removed ## to uncomment the 2 lines)
>> Do you understand why ?
>>
>> class my_property:
>>      def __init__(self, fget=None, fset=None, fdel=None):
>>          self.fget = fget
>>          self.fset = fset
>>          self.fdel = fdel
>>      def __set_name__(self, owner, name):
>>          self._name = name
>>          print("Inside __set_name__ method:  ", self._name)
>>
>>      def __get__(self, instance, owner):
>>          return self.fget(instance)
>>
>>
>> class Test:
>>      celsius = my_property()
>>
>> print("Outside __set_name__ method: ", Test.celsius._name)
>>
>> Here is the output:
>>
>> ========= RESTART: C:/Users/jm/Desktop/python/my_property.py =========
>> Inside __set_name__ method:   celsius
>> Traceback (most recent call last):
>>    File "C:/Users/jm/Desktop/python/my_property.py", line 17, in <module>
>>      print("Outside __set_name__ method: ", Test.celsius._name)
>>    File "C:/Users/jm/Desktop/python/my_property.py", line 11, in __get__
>>      return self.fget(instance)
>> TypeError: 'NoneType' object is not callable


More information about the Python-list mailing list