python中__getattribute__和__get__之间有啥联系和区别?

如果run以下代码

class A:
    def __get__(self,instance,owner):
        print('正在进行get操作')
        
class B:
    x = A()
    def __getattribute__(self,name):
        print('正在进行getattribute操作')

a = B()
a.x

结果是:正在进行getattribute操作

如果run这个代码

class A:
    def __get__(self,instance,owner):
        print('正在进行get操作')
        
class B:
    x = A()
a = B()
a.x

结果就是:正在进行get操作
为什么

这么写关系可能更明显一些
img

两者表现很像,但是本质上不同。
首先说__get__这个方法,它是描述器的专有方法,如果一个类有这个方法,那这个类就被称为描述器,描述器必须实例化并作为另一个类(所有者)的属性存在。而通过所有者调用它的描述器属性时会触发__get__方法。
而__getattribute__方法会无条件地被调用以实现对类实例属性的访问。如果类还定义了__getattr__(),则后者不会被调用,除非__getattribute__() 显式地调用它或是引发了 AttributeError。换句话说它会把任何属性访问替换成它本身,所以你第一次的代码访问a.x不会打印get,因为你并没有真正访问到描述器实例,你只是触发了__getattribute__方法,想要在__getattribute__方法中使用属性,需要调用具有相同名称的基类方法object.__getattribute__(self, name)来真正访问这个属性

getattribute 优先级高于 get