描述符

描述符:

本质是一个新式类,在这个新式类中至少实现了__get__(),set(),
del()中的一个,也被称为描述符协议
?为什么是新式类?
get()调用属性时触发
set()为一个属性赋值时触发
del()采用del删除属性时,触发

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

ps:描述符类产生的实例进行属性操作时并不会触发三个方法的执行

当描述符被定义成另外一个类的类属性,当该属性被调用,赋值,删除时触发描述的三个方法执行

描述符分两种:
数据描述符:至少实现了__get__()和__set__()
非数据描述符:没有实现__set__()
?实现了set,没实现get的叫啥?
是不是说实现set的前提是需实现get,先获得属性,再设置属性

注意事项:
1.描述符本身应该定义成新式类,被代理的类也应该是新式类
2.必须把描述符定义成这个类的类属性,不能定义到构造函数中
3.要严格遵循优先级,由高到低分别为:
①类属性
②数据描述符
③实例属性
④非数据描述符
⑤找不到的属性触发__getattr__

定义成一个类的类属性,规范属性的行为

class Typed:

self,描述符的实例化对象,instance,使用描述符的类的实例对象,当类直接调用时为None

owner 使用描述符的类,value实例化时传入的值

def __init__(self,name,expected_type):
    self.name=name
    self.expected_type=expected_type
def __get__(self, instance, owner):#为什么要owner,没用到啊
    print('get--->',instance,owner)
    if instance is None:
        return self
    return instance.__dict__[self.name]

def __set__(self, instance, value):
    print('set--->',instance,value)
    if not isinstance(value,self.expected_type):#限定类型
        raise TypeError('Expected %s' %str(self.expected_type))
    instance.__dict__[self.name]=value
def __delete__(self, instance):
    print('delete--->',instance)
    instance.__dict__.pop(self.name)

class People:
name=Typed('name',str)
age=Typed('name',int)
salary=Typed('name',float)
def init(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary

class Typed:
def init(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def get(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.dict[self.name]

def __set__(self, instance, value):
    print('set--->',instance,value)
    if not isinstance(value,self.expected_type):
        raise TypeError('Expected %s' %str(self.expected_type))
    instance.__dict__[self.name]=value
def __delete__(self, instance):
    print('delete--->',instance)
    instance.__dict__.pop(self.name)

def typeassert(**kwargs):
def decorate(cls):
print('类的装饰器开始运行啦------>',kwargs)
for name,expected_type in kwargs.items():#解压赋值,
setattr(cls,name,Typed(name,expected_type))#将描述符设置为类属性
return cls
return decorate

@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
def init(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary

print(People.dict)
p1=People('egon',18,3333.3)

posted @ 2018-12-17 21:26  robertzhou  阅读(244)  评论(0编辑  收藏  举报