Python描述符__get__(),__set__(),__del__()

1、什么是描述符

1、从字面意思:假设一个人,这个人有很多的属性(名字、年龄、升高、体重等),而描述符就是对这些属性的限制,及描述符就是对对象属性的一种限制,或者说在对象赋予这个属性之前的一种操作(扩展)

2、描述符协议

注意:python3以后,自定义的类都是新式类,python2中class MyClass(object)才是新式类
一个新式类中,至少实现了__get__(),set(),delete()中的一个,这也被称为描述符协议:
get():调用一个属性时,触发
set():为一个属性赋值时,触发
delete():采用del删除属性时,触发

3、描述符的作用

描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数“init()”中)

4、描述符分的分类

1、数据描述符:至少实现了__get__()和__set__()
2、非数据描述符:没有实现__set__()

5、描述符定义要求

1、描述符及被代理的类都必须是新式类
2、描述符必须是代理类的类属性,不能在__init__方法中定义
3、要严格遵循该优先级,优先级由高到底

6、类属性、描述符、实例属性的优先级

优先级由高到底:
    1.类属性
    2.数据描述符
    3.实例属性
    4.非数据描述符
    5.找不到的属性触发__getattr__()

五、描述符的应用

PeoPel表示人类,实例化一个人的对象,这个对象有name,age,height,weight

# 数据描述符
class A:
    def __init__(self, key, DesType):
        self.key = key  # 属性名
        self.DesType = DesType  # 属性值的类型
    def __set__(self, instance, value):
   		# instance:表示被代理类,实例化的对象
   		# value:被赋予的属性值
        print(value, 'set')
        if not isinstance(value, self.DesType):
            raise TypeError("%s is not %s" % (value, self.DesType))
        instance.__dict__[self.key] = value
    def __get__(self, instance, owner):
    	# instance:表示被代理类,实例化的对象
    	# owner:表示被代理类
        print(instance.__dict__[self.key], 'get')
        return instance.__dict__[self.key]
class B:
    name = A('name', str)  # 表示B类name属性被代理了
    def __init__(self):
        self.name = "张三"  # 就是给name赋值,触发代理类__set__方法
if __name__ == "__main__":
    obj = B()
    print(obj.name, 'B实例的name属性')   # obj.name获取name属性是触发__get__方法
# 输出结果:
张三 set
张三 get
张三 B实例的name属性

# 非数据描述符
class A:
    def __init__(self, key, DesType):
        self.key = key
        self.DesType = DesType
    def __get__(self, instance, owner):
        print(instance.__dict__[self.key], 'get')
        return instance.__dict__[self.key]
class B:
    name = A('name', str)  # 表示B类name属性被代理了
    def __init__(self):
        self.name = "张三"  # 就是给name赋值,触发代理类__set__方法
if __name__ == "__main__":
    obj = B()
    print(obj.name, 'B实例的name属性')   # obj.name获取name属性是触发__get__方法
# 输出结果:
张三 B实例的name属性  # 非数据描述符没有触发__get__(),实例属性优先

# 类属性
class A:
    def __init__(self, key, DesType):
        self.key = key
        self.DesType = DesType
    def __set__(self, instance, value):
        print(value, 'set')
        if not isinstance(value, self.DesType):
            raise TypeError("%s is not %s" % (value, self.DesType))
        instance.__dict__[self.key] = value
    def __get__(self, instance, owner):
        print(instance.__dict__[self.key], 'get')
        return instance.__dict__[self.key]
class B:
    name = A('name', str)  # 表示B类name属性被代理了
    def __init__(self):
        self.name = "张三"  # 就是给name赋值,触发代理类__set__方法
if __name__ == "__main__":
    obj = B()
    B.name = '李四'  # name重新赋值属于类属性,而不是描述符了
    obj.name = "sss" # 实例重新赋值,name没有被描述符代理,不会触发__set__方法
    print(obj.name, 'B实例的name属性')   # obj.name获取name属性是触发__get__方法

结果:
张三 set
sss B实例的name属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值