属性描述符可以用来控制给属性赋值的时候的一些行为
import numbers 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') self.value = value def __delete__(self, instance): pass class User: age = IntField() if __name__ == '__main__': user = User() user.age = 30 #此语句相当于执行了属性描述符中的__set__()方法。形数value对应实参30 print(user.age)
此代码中自定义的IntField类就是属性描述符类,属性描述根据其实现的魔法方法分为数据描述符和非数据描述符,两者的优先级别不一样。如果定义了属性描述符,那么在下面的类中定义属性的时候,如果属性是属性描述符的实例,那么再给属性赋值的时候就会先调用属性描述符中的__set__方法。
数据描述符:
类中同时实现了__get__ 和__set__方法。
非数据描述符
类中只实现了__get__ 方法。
属性描述符中属性的查找顺序
user = User(),那么user.age顺序如下:
- 到数据描述符中调用__get__方法。
- 查找自身实例的age属性
- 调用对象的age属性。如果没有
- 调用非数据描述符的__get__方法。
- 如果有__getattr__方法,调用其方法
- 都没有抛出异常