描述符

描述符的本质就是新式类,其至少实现了__get__(),__set__(),__delete__()中的一个,也被称为描述符协议;

__get__():在调用一个属性时,触发

__set__():在为一个属性赋值时,触发

__delete__():在用del删除属性时,触发

描述符的作用:用来代理另一个类的类属性(必须是类属性,不能在类的函数构造中),且描述符在自身调用,赋值,删除属性时不会被触发

class Str:
    def __get__(self, instance, owner):
        print('触发Strget',instance,owner)
    def __set__(self, instance, value):
        print('触发Strset',instance,value)
    def __delete__(self, instance):
        print('触发Strdel')
class Int:
    def __get__(self, instance, owner):
        print('触发Intget',instance,owner)
    def __set__(self, instance, value):
        print('触发Intset',instance,value)
    def __delete__(self, instance):
        print('触发Intdel')
class People:
    name=Str()
    age=Int()
    def __init__(self,name,age):
        self.name=name
        self.age=age

#自身的实例不会触发
s=Str()
s.x=1
del s.x
i=Int()
i.y=2
del i.y

#实例化people时触发
p=People('alex',18)

#描述符Str的使用
p.name
p.name='Bart'
del p.name

#描述符Int的使用
p.age
p.age=19
del p.age

print(p.__dict__)#为空,因为name和age属性被Str和Int代理,在Str和Int中处理,并没有写入p.__dict__中
print(People.__dict__)

描述符分两种一 数据描述符:

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

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

注意:

一 描述符本身应该定义成新式类,被代理的类也应该是新式类
二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
三 要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()

class Str:
    def __get__(self, instance, owner):
        print('触发Strget',instance,owner)
    def __set__(self, instance, value):
        print('触发Strset',instance,value)
    def __delete__(self, instance):
        print('触发Strdel')
class People:
    name=Str()
    def __init__(self,name):
        self.name=name

#类属性>数据描述符>实例属性
#数据符大于实例属性
p=People('Alex')#触发了__set__
p.name           #触发了__get__
p.name='Bart'   #触发了__set__
del p.name       #触发了__delete__
print(p.__dict__)

#类属性大于数据描述符
print('====>',People.__dict__['name'])
People.name='Bart'#不会触发__set__,直接People.__dict__中name对应的值由__set__的内存地址改为Bart
print('====>',People.__dict__['name'])
print(p.name)             #不再触发__get__
class Str:
    def __get__(self, instance, owner):
        print('触发Strget',instance,owner)
    # def __set__(self, instance, value):
    #     print('触发Strset',instance,value)
    # def __delete__(self, instance):
    #     print('触发Strdel')
class People:
    name=Str()
    def __init__(self,name):
        self.name=name

#实例大于非数据描述符
p=People('Alex')
p.name
p.name='Bart'
#都不会触发

描述符的作用

描述符可以规定输入的值的类型

class Type:
    def __init__(self,key,type):
        self.key=key
        self.type=type
    def __get__(self, instance, owner):
        print('触发get')
        return instance.__dict__[self.key]
    def __set__(self, instance, value):
        print('触发set')
        if not isinstance(value,self.type):
            raise TypeError('%s不是%s'%(value,self.type))
        else:
            instance.__dict__[self.key]=value
    def __delete__(self, instance):
        print('触发del')
class People:
    name=Type('name',str)
    age=Type('age',int)
    salary=Type('salary',float)
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary
p1=People("alex",18,3000.0)
print(p1.__dict__)
p2=People('bart','18',3000)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值