python描述符__get__,__getattribute__等属性引用机制

问题1:__dict__魔术属性是什么?
    python中的元对象object中定义了__dict__属性,其以字典的形式用来承载类中的属性和方法。类的__dict__和类实例对象的__dict__存储的内容不同,类的__dict__存储了类的方法,类变量,静态方法等;实例类的__dict__中存储了自己定义的属性和方法,类变量不在此中存储。例如:
class Foo:
    x=TestMain("hello")
    def __init__(self):
        self.x="jk"#t的实例属性
t = Foo()
print(t.__dict__)#只存储了实例属性{'x': 'jk'}
print(Foo.__dict__)#{'__module__': '__main__', '__doc__': None, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__init__': <function Foo.__init__ at 0x7f12724caa60>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, 'x': <__main__.TestMain object at 0x7f12724cbb38>}
     问题2:如下例子,如果我们执行print(b),程序内部是如何执行的?对象的属性引用是偏底层的知识。首先区分一下概念:实例属性,属于实例t所拥有的变量,如self.name;类属性,属于类Foo所拥有的类变量,如name="jlkdjl".
class Foo():
    name="jlkdjl"  #Foo的类属性,优先级为3
    def __getattr__(self, item): 优先级为4
        print("foo getattr")
        return ("djkjkd")
    def __init__(self):
        self.name=1223  #t的实例属性,优先级为2
    def __getattribute__(self, item):#优先级为1
        print("j111")

if __name__ == '__main__':
    t = Foo()
    b=t.name
    print(b)
     在python中所有类都继承自object类,其自带__getattribute__魔术方法,属性引用时,其优先级最高。当执行b=t.name时,解释器就会依以下顺序进行查找,找到就返回:执行obj.__getattribute__()------,查找实例属性----------,-----查找类属性-----,执行__getattr__(如果类中有此方法)-----。
    
问题3:__get__是什么?
     这里涉及到一个概念描述符,描述符是用来描述捆绑行为的。如果想将一个对象a当做另一对象b的属性进行处理,可以将这个对象a构造成描述符,之后可以采用b.a访问a。python定义,含有__get__、__set__方法的对象叫数据描述符,非数据描述符是只含__get__方法的对象。描述符本质是一个对象,其含有__get__等方法,可以将自身绑定到另一对象上,充当其的属性。例如:对象TestMain是一个描述符,其充当了Func的一个类属性name。
class TestMain:#描述符
    def __init__(self,name):
        self.n= name
    def __get__(self, instance, owner):
        print(2222)
        return self.n()
    def __set__(self, instance, value):#不含set时,是非数据描述符
        print(1111)
        print("jksdjlsjdfl")
class Func():
    name=TestMain()
    问题4:含有__get__方法的对象,其内部属性引用的机制是什么?
    对象属性的引用分为普通对象属性的引用和含有描述符的对象属性引用。问题2是普通对象属性引用的查找机制。对于描述符,例如调用b.a,其查找机制为:执行obj.__getattribute__()------,查找数据描述符(通过调用__getattribute__将b.a转化为type(b).__getattribute__(a).__get__()),-------查找实例属性----------,-----查找类属性-----,查找非数据描述符------,执行__getattr__-----。即数据描述符的优先级要大于实例属性的优先级和类属性。

class TestMain:
    def __init__(self,name):
        self.n= name
    def __get__(self, instance, owner):
        print(2222)
        return self.n()
    def __set__(self, instance, value):#不含set时,是非数据描述符
        print(1111)
        print("jksdjlsjdfl")


class Foo():
    name=TestMain()#数据描述符,优先级1
    def __init__(self):
        self.name="hello"#实例属性,优先级2
    
a=Foo.name#执行时,会触发__get__方法
print(a)


a=Foo()#因定义了一个实例,其self.name优先级低于类属性name。执行__init__语句时,其self.name会触发__set__方法。
b=a.name#执行时,会触发__get__方法
print(a)
    问题5 基于描述符的使用,所谓的classmethod,property装饰器的形成过程?
原文地址:https://www.cnblogs.com/xuehaiwuya0000/p/11267915.html