Suppose cls
is a class in python. cls.__getattribute__
returns the __getattribute__
function defined on object
, but it doesn't bind cls
to this function. According to the descriptor protocol, cls
is an instance of object
and if an attribute is found on the class dictionary, it should return a bound method with cls
bound to it.
The same call with cls.__call__
returns a bound method with cls
bound to the __call__
function defined on type
. Why is there a difference? Also why doesn't cls.__getattribute__
find the attribute in type
?
class cls:
pass
[In]: cls.__getattribute__
[Out]: slot wrapper '__getattribute__' of 'object' objects>
[In]: object.__getattribute__
[Out]: <slot wrapper '__getattribute__' of 'object' objects>
[In]: cls.__getattribute__ is object.__getattribute__
[Out]: True
[In]: cls.__call__
[Out]: <method-wrapper '__call__' of type object at 0x7fdee07ad110>
[In]: type.__call__.__get__(cls)
[Out]: <method-wrapper '__call__' of type object at 0x7fdee07ad110>
When you look up cls.__getattribute__
, that gets found in cls
's own MRO, on cls
's superclass object
. Like any other method found this way, the lookup returns an unbound method representing the __getattribute__
method of instances of the class.
On the other hand, when you look up cls.__call__
, that doesn't get found in cls
's MRO. cls
's MRO is (cls, object)
, and neither cls
nor object
defines a __call__
method. Instead, this method gets found on cls
's own class, its metaclass: it gets found on type
. As with any other method found this way, the resulting method is bound to the instance the lookup happened on, that instance being cls
itself.
Thus, cls.__getattribute__
represents the unbound method for getting attributes on instances of cls
, while cls.__call__
represents a bound method for calling cls
itself.