首页 > 其他 > 详细

33.描述器(二)

时间:2021-06-11 10:44:14      阅读:16      评论:0      收藏:0      [点我收藏+]

 

 

(三十四)描述器二

 

4:数据描述器

 

    # 示例1:
    class XKD1:
        def __init__(self):
            self.course = Python
            print(XKD1.__init__)
        def __get__(self, instance, owner):
            # 这里的self为XKD1的实例. instance为实例, 如果是类访问,那么instance为None. owner是调用者的类
            print(self={} instance={} owner={}.format(self, instance, owner))
            # todo: 返回XKD1的实例self
            return self
    class XKD2:
        x = XKD1()
        def __init__(self):
            print(XKD2.__init__)
            self.y = XKD1()   # 没有调用__get__方法
    print(**100)
    print(XKD2.x.course) # self=<__main__.XKD1 object at 0x108c39b38> instance=None owner=<class __main__.XKD2>
    print(**100)
    obj = XKD2()
    print(**100)
    print(obj.y)   # 返回 <__main__.XKD1 object at 0x103b56cf8>
    小结: 当非数据描述器是实例的变量时,实例访问非数据描述器不会调用__get__方法,只是访问了描述器类的实例
    # 示例2:数据描述器
    class XKD1:
        def __init__(self):
            self.course = Python
            print(XKD1.__init__)
        def __get__(self, instance, owner):
            print(self={} instance={} owner={}.format(self, instance, owner))
            return self
        def __set__(self, instance, value):
            print(self={} instance={} value={}.format(self, instance, value))
            self.course = value
    class XKD2:
        x = XKD1()
        def __init__(self):
            print(XKD2.__init__)
            self.y = XKD1()   # 调用了__get__方法
    print(**100)
    print(XKD2.x.course)
    print(**100)
    obj = XKD2()
    print(**100)
    print(obj.x)
    小结: 当数据描述器是实例的变量时,实例访问数据描述器会调用描述器的__get__方法

 

5:非数据描述器和数据描述器的访问顺序

 

    # 示例1:非数据描述器
    class XKD1:
        def __init__(self):
            self.course = Python
            print(XKD1.__init__)
        def __get__(self, instance, owner):
            print(self={} instance={} owner={}.format(self, instance, owner))
            return self
    class XKD2:
        x = XKD1()
        def __init__(self):
            print(XKD2.__init__)
            self.x = XKD1          # 实例访问的是自己的__dict__中的x属性
    print(**100)
    print(XKD2.x.course)
    print(**100)
    obj = XKD2()
    print(**100)
    print(obj.x)  # 返回 XKD1
    # 示例2:数据描述器
    class XKD1:
        def __init__(self):
            self.course = Python
            print(XKD1.__init__)
        def __get__(self, instance, owner):
            print(self={} instance={} owner={}.format(self, instance, owner))
            return self
        def __set__(self, instance, value):
            print(self={} instance={} value={}.format(self, instance, value))
            self.course = value
    class XKD2:
        x = XKD1()
        def __init__(self):
            print(XKD2.__init__)
            self.x = XKD1          # 实例这里访问的是类属性x,也就是数据描述器,会调用数据描述器的__get__方法
    print(**100)
    print(XKD2.x.course)
    print(**100)
    obj = XKD2()
    print(**100)
    print(obj.x)  # 调用__get__方法,返回 XKD1实例
    小结: 一个类实例的查找属性顺序为:先查找类或父类中的数据描述器属性, 在查找自己__dict__中的属性,再查找类或父类的非数据描述器, 数据描述器优先于实例的__dict__, 实例的__dict__属性优先于非数据描述器, 当存在描述器的时候,属性的查找顺序为:类或父类的数据描述器属性 --> 实例的__dict__属性 --> 类或父类的非数据描述器属性

 

 

 

4.数据描述器

  • 当非数据描述器是实例的变量时,实例访问非数据描述器不会调用__get__方法,只是访问了描述器类的实例;

  • 当数据描述器是实例的变量时,实例访问数据描述器会调用描述器的__get__方法;

5.非数据描述器和数据描述器的访问顺序

当存在描述器的时候,一个类实例的查找属性顺序为:先查找类或父类中是否有数据描述器属性,如果有那么,先访问数据描述器,如果没有数据描述器 --> 那么就会查找自己实例的__dict__属性,如果__dict__属性里面也没有找到 --> 就会在类或父类的非数据描述器中进行查找;

 

33.描述器(二)

原文:https://www.cnblogs.com/zhongguiyao/p/14873810.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!