I am trying to understand descriptors in python, and one thing I noticed is the following:
In [1]: class descriptor:
...: def __init__(self):
...: pass
...: def __get__(self, instance, owner):
...: print ("__get__ called")
...: return 0
...: def __set__(self, obj, value):
...: print ("__set__ called")
In [2]: class Foo:
...: y = descriptor()
...: def __init__(self):
...: self.x = descriptor()
In [3]: Foo.y
__get__ called
Out[3]: 0
In [4]: f = Foo()
In [5]: f.x
Out[5]: <__main__.descriptor at 0x1099dd588>
As you can see, on the class attribute, descriptor's __get__ is being correctly called, but on instance attribute it is not calling the required method. I tried reading this, but it is not immediately obvious what part of that page applies over here.
Descriptors are only supported on the class, never on an instance.
See the Invoking Descriptors section of the reference datamodel documentation:
Bold emphasis mine. Here, owner class is the class of the instance you accessed the attribute on, or in case of accessing the attribute on the class, the class itself is the owner class.