版权声明:转载请注明出处。 https://blog.csdn.net/paopaohll/article/details/83177744
属性描述符简介
描述符对象一般是作为其他类对象的属性而存在。在其内部定义了三个方法用来实现属性对象的查找、设置、删除行为。这三个方法分别是:
- get(self, instance, owner):定义当试图取出描述符的值时的行为。
- set(self, instance,value):定义当描述符的设定值或改变时的行为。
- delete(self, instance):定义当描述符的值被删除时的行为。
- 只要实现__get__、set、__delete__方法中的一个就可以认为是描述符;
- 只实现__get__方法的对象是非数据描述符,在初始化之后它们只能被读取;
- 同时实现__get__和__set__的对象是数据描述符,这种属性是可读写的。
属性描述符查找过程
首先调用__getattribute__。如果类定义了__getattr__方法, 那么在__getattribute__抛出AttributeError 的时候就会调用到__getattr__,而对于描述符__get__的调用,则是发生在__getattribute__内部的。
class IntField:
#数据描述符
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
if not isinstance(value, numbers.Integral):
raise ValueError("int value need")
if value < 0:
raise ValueError("positive value need")
self.value = value
def __delete__(self, instance):
pass
class NonDataIntField:
#非数据属性描述符
def __get__(self, instance, owner):
return self.value
class User:
age = IntField()
# age = NonDataIntField()
user = User()
那么user.age查找顺序如下:
(1)如果“age”是出现在User或其基类的__dict__中, 且age是data descriptor, 那么调用其__get__方法, 否则
(2)如果“age”出现在user的__dict__中, 那么直接返回 obj.__dict__[‘age’], 否则
(3)如果“age”出现在User或其基类的__dict__中
(3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
(3.2)返回 __dict__[‘age’]
(4)如果User有__getattr__方法,调用__getattr__方法,否则
(5)抛出AttributeError