''' 1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议 __get__():调用一个属性时,触发 __set__():为一个属性赋值时,触发 __delete__():采用del删除属性时,触发 2.描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中) 3.描述符分两种 一:数据描述符---至少实现了__get__()和__set__() 二:非数据描述符---没有实现__set__() 4.注意事项 一:描述符本身应该定义成新式类,被代理的类也应该是新式类 二:必须把描述符定义成这个类的类属性,不能为定义到构造函数中 三:要严格遵循该优先级,优先级由高到底分别是 a.类属性 b.数据描述符 c.实例属性 d.非数据描述符 e.找不到的属性触发__getattr__() ''' # #描述符Str # class Str: # def __get__(self, instance, owner): # print('Str调用') # # def __set__(self, instance, value): # # self是name(Str实例化的对象),instance是p1,value是'alex' # print('Str设置...') # # def __delete__(self, instance): # print('Str删除...') # # #描述符Int # class Int: # def __get__(self, instance, owner): # print('Int调用') # # def __set__(self, instance, value): # print('Int设置...') # # def __delete__(self, instance): # print('Int删除...') # # class People: # name = Str() # age = Int() # def __init__(self, name, age): #name被Str类代理,age被Int类代理, # self.name = name # self.age = age # # #何地?:定义成另外一个类的类属性 # # #何时?:且看下列演示 # # p1 = People('alex', 18) # print(p1.__dict__) # print(People.__dict__) # 'name': <__main__.Str object at 0x000001EA4C7D3D30>, 'age': <__main__.Int object at 0x000001EA4C840190> # # #描述符Str的使用 # p1.name # p1.name = 'egon' # del p1.name # # #描述符Int的使用 # p1.age # p1.age = 18 # del p1.age # # #我们来瞅瞅到底发生了什么 # print(p1.__dict__) # print(People.__dict__) # # #补充 # print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的 # print(type(p1).__dict__ == People.__dict__) '''类属性>数据描述符''' # class Foo: # def __set__(self, instance, value): # print('---set') # # def __get__(self, instance, owner): # print('---get') # # def __delete__(self, instance): # print('---delete') # # class Bar: # x = Foo() # # def __getattr__(self, item): # return '找不到此属性%s' % item # # print(Bar.x) # ---get None(__get__方法没有返回值) # # Bar.x = 1 # 不会触发__set__ # print(Bar.x) # 1 # # del Bar.x # 不会触发__delete__ # print(Bar.__dict__) # 属性x已经被删除 '''数据描述符>实例属性(类属性和实例属性同名)''' # class Foo_1: # def __set__(self, instance, value): # print('---set') # # def __get__(self, instance, owner): # print('---get') # # def __delete__(self, instance): # print('---delete') # # class Car: # name = Foo_1() # def __init__(self, name): # self.name = name # # c1 = Car('bmw') # ---set 初始化设置值 # print(c1.__dict__) # {} 实例属性字典为空 # print(c1.name) # ---get None 获取值 # del c1.name # ---delete 删除 # c1.name = 'audi' # ---set # print(c1.__dict__) # {} '''实例属性>非数据描述符''' # class Foo_2: # def __get__(self, instance, owner): # print('---get') # # class Func: # name = Foo_2() # def __init__(self, name): # self.name = name # # ff = Func('alex') # print(ff.__dict__) # {'name': 'alex'} # print(ff.name) # 'alex' '''非数据描述符>__getattr__''' # class Foo_3: # def __get__(self, instance, owner): # print('---get') # # class Func_1: # name = Foo_3() # def __init__(self, name): # self.name = name # # def __getattr__(self, item): # print('找不到此属性') # # aa = Func_1('wupeiqi') # print(aa.name) # aa.age # 找不到此属性