描述符

一、概念:

Python 中,通过使用描述符,可以让程序在引用一个对象属性时自定义要完成的工作。

本质上看,描述符就是一个类,只不过它定义了另一个类中属性的访问方式。

换句话说,一个类可以将属性全权委托给描述符类。

描述符类基于以下3个特殊方法:

♦ __set__ (self, instance, value)   设置属性调用

♦ __get__(self,instance, owner) 访问属性调用

♦ __delete__(self, instance) 对属性调用del 时将调用这一方法

二、描述符分两种

①数据描述符:至少实现了 __get__()和__set__()

class Foo:
    def __set__(selfsself,instance, value):
        print("set")
    def __get__(self, instance, owner):
        print("get")
        

②非数据描述符:没有实现__set__()

class Foo:

    def __get__(self, instance, owner):
        print("get")

实例:  

class Foo:
    def __get__(self, instance, owner):   #这里的instance是实例对象b1,owner是类Bar
        print("===>get方法")
        return instance.__dict__['x']
    def __set__(self, instance, value):  #这里的instance是实例对象b1,value是传入的值
        print("===>set方法")
        instance.__dict__['x'] = value
    def __delete__(self, instance):
        print("===>delete方法")
        instance.__dict__.pop('x')

class Bar:
    x = Foo()   #将x 全权给Foo类代理,此时 x 就是描述符
    def __init__(self, n):
        self.x = n

b1 = Bar(10)
print(b1.__dict__)
print(b1.x)
del b1.x
print(b1.__dict__)
b1.x = 222222222
print(b1.__dict__)
b1.y = 2222
print(b1.__dict__)

  

三、描述符优先级

类属性 > 数据描述符 > 实例属性 > 非数据属性 > 找不到的属性触发__getattr__

class Foo:
    def __get__(self, instance, owner):   #这里的instance是实例对象b1,owner是类Bar
        print("===>get方法")
        # return instance.__dict__['x']
    def __set__(self, instance, value):  #这里的instance是实例对象b1,value是传入的值
        print("===>set方法")
        # instance.__dict__['x'] = value
    def __delete__(self, instance):
        print("===>delete方法")
        # instance.__dict__.pop('x')
class Bar:
    x = Foo()
    def __init__(self, n):
        self.x = n

b1 = Bar(10)
print(Bar.__dict__)  #这里打印字典看出:x 是一个对象
Bar.x = 10
print(Bar.x)
print(Bar.__dict__)  #当Bar.x为x后,直接覆盖了描述符的操作

class Foo:
    def __get__(self, instance, owner):   #这里的instance是实例对象b1,owner是类Bar
        print("===>get方法")
        # return instance.__dict__['x']
    def __set__(self, instance, value):  #这里的instance是实例对象b1,value是传入的值
        print("===>set方法")
        # instance.__dict__['x'] = value
    def __delete__(self, instance):
        print("===>delete方法")
        # instance.__dict__.pop('x')
class Bar:
    x = Foo()
    def __init__(self, n):
        self.x = n

b1 = Bar(10)
b1.x = 10  #可以看出。用实例为变量赋值时,直接触发数据描述符
print(b1.__dict__)

  

class Foo:
    def __get__(self, instance, owner):   #这里的instance是实例对象b1,owner是类Bar
        print("===>get方法")
        # return instance.__dict__['x']
    # def __set__(self, instance, value):  #这里的instance是实例对象b1,value是传入的值
    #     print("===>set方法")
    #     # instance.__dict__['x'] = value
    # def __delete__(self, instance):
        print("===>delete方法")
        # instance.__dict__.pop('x')
class Bar:
    x = Foo()
    def __init__(self, n):
        self.x = n

b1 = Bar(10)
b1.x = 10  #可以看出。用实例为变量赋值时,没有触发非数据描述符
print(b1.__dict__)

 

class Foo:
    def __get__(self, instance, owner):   #这里的instance是实例对象b1,owner是类Bar
        print("===>get方法")
        # return instance.__dict__['x']
    # def __set__(self, instance, value):  #这里的instance是实例对象b1,value是传入的值
    #     print("===>set方法")
    #     # instance.__dict__['x'] = value
    # def __delete__(self, instance):
        print("===>delete方法")
        # instance.__dict__.pop('x')
class Bar:
    x = Foo()
    def __init__(self, n):
        self.x = n
    def __getattr__(self, item):
        print("qaq")

b1 = Bar(10)
b1.yyyy   #当查找的属性不存在时

  

  

posted @ 2019-10-07 15:37  绝世刘  阅读(228)  评论(0编辑  收藏  举报