1.概念:可以描述一个属性操作的对象。
1.1对象:
1.2属性的操作:增/改、删、查
1.3描述:
2.作用:
3.定义:
3.1定义方式1:property
class Person: # def __init__(self): # self.__age = 10 # def get_age(self): # return self.__age # def set_age(self, value): # if value < 0: # value = 0 # self.__age = value # def del_age(self): # del self.__age # age = property(get_age, set_age, del_age) @property def age(self): return self.__age @age.setter def age(self, value): if value < 0: value = 0 self.__age = value @age.deleter def age(self): del self.__age # p = Person() # # p.set_age(-10) # # print(p.get_age()) # # p.del_age() # # print(p.get_age()) # # p.age = 19 # print(p.age) # del p.age # print(p.age) # help(Person) p = Person() p.age = 19 print(p.age)
3.2定义方式2:
class Age: def __get__(self, instance, owner): print("get") def __set__(self, instance, value): print("set") def __delete__(self, instance): print("delete") class Person: age = Age() p = Person() p.age = 100 print(p.age) del p.age
4.调用细节
4.1当我们定义好一个描述器的时候。调用的时候一定是通过类实例化的对象来进行调用操作,才能使增删改查完美的转换。不能使用类本身来进行调用。使用类本身进行调用,增、改、删、无法实现。
4.2描述器只能在新式类当中才能实现。在经典类中无法实现。并且类都必须为新式类
4.3方法拦截:
一个实例属性正常的访问顺序:实例对象自身的__dict__字典->对应类对象的__dict__字典->如有父类,会往上层的__dict__字典中检测。->如果没有找到,又定义了__getattr__方法,就会调用这个方法。
而在上述的整个过程当中,是如何将描述器的__get__方法给嵌入到查找机制当中?就是通过这个方法进行实现的:__getattribute__
内部模拟实验:如果实现了描述器方法__get__就会直接调用。如果没有,则按照上面的机制去查找。
如果重写了 __getattribute__,则__get__就会被拦截。
4.4描述器与实力属性操作优先级问题:
描述器分为:资料描述器与非资料描述器。
资料描述器:实现了get、set这两个方法,这就是一个资料描述器。
非资料描述器:仅仅实现了get方法,那么这就是一个非资料描述器。
资料描述器 > 实例属性 > 非资料描述器。
class Age(object): def __get__(self, instance, owner): print("get") # def __set__(self, instance, value): # print("set") # def __delete__(self, instance): # print("delete") class Person(object): age = Age() def __init__(self): self.age = 10 p = Person() p.age = 100 print(p.age) # del p.age print(p.__dict__) # print(Person.age) # Person.age = 19 # del Person.age # 4.4 # 描述器与实力属性操作优先级问题: # # 描述器分为:资料描述器与非资料描述器。 # # 资料描述器:实现了get、set这两个方法,这就是一个资料描述器。 # # 非资料描述器:仅仅实现了get方法,那么这就是一个非资料描述器。 # # 资料描述器 > 实例属性 > 非资料描述器。
5.注意:以下案例中,age是共享的,数据存储在instance中。
# -------------------------------------------------描述器的存储问题----------------------------------------------------- class Age(object): def __get__(self, instance, owner): print("get") return instance.v def __set__(self, instance, value): print("set", self, instance, value) instance.v = value def __delete__(self, instance): print("delete") del instance.v class Person(object): age = Age() p = Person() p.age = 100 print(p.age) # del p.age p2 = Person() p2.age = 11 print(p2.age) print(p.age)