Search code examples
pythondescriptormagic-methods

why object of class does not call __get__ and __set__ i.e descriptor methods?


Class is as follows

class Descriptor(object):
    def __init__(self,name=None):
        self.n = name
    def __get__(self,instance,cls):
        print ("Get",self.n)
    def __set__(self,instance,value):
        print ("set",self.n,value)

Now if I create object of Descriptor class and access attribute n, then shouldn't it access the __get__ method?

obj = Descriptor() 
print (obj.n)

If I create another class which inherits Descriptor class and I create object of Descriptor inside derived class, then __get__ and __set__ are getting called.

class Test(Descriptor):
    d = Descriptor("ansh")

t = Test()
print (t.d)

I am confused by this behavior.

According to the docs, descriptors are invoked by the __getattribute__() method object.__getattribute__() and type.__getattribute__() make different calls to __get__(), what is object.__getattribute__() over here?


Solution

  • obj.n is not a descriptor object. It doesn't have any methods that would make it a descriptor. type(obj).__dict__['n'].__get__ does not exist. It is just a string object.

    The fact that obj itself has such methods doesn't matter here, because obj is not the attribute, obj.n is.

    t.d is a descriptor object, type(t).__dict__['d'].__get__ does exist. So when you access t.d, you get the result of the call to the __get__ method.

    It is always the attribute itself that implement the descriptor protocol. It must directly have descriptor methods for those to be called.