import numbers class Intfield: # 数据属性描述符 ,实现了get和set def __get__(self, instance, owner): return self.value def __set__(self, instance, value): if not isinstance(value, numbers.Integral): raise ValueError('argument must be digital') self.value = value def __delete__(self, instance): pass
class NoneDataIntField: # 非数据属性描述符,只实现了其中一种方法 def __get__(self, instance, owner): pass
class User: age = Intfield() if __name__ == '__main__': user = User() user.age = 'abc' # print(user.birthday.year) # print(user.age) print(user.age)
如果user 是某个类的实例,那么user.age(以及等价的getattr(user, 'age'))
首先调用 __getattribute__。如果类定义了__getattr__方法,那么在__getattribute__抛出AttributeError的时候就会调用到__gettattr__,而对于描述符(__get__)的调用, 则发生在__getattribute__内部的。
user = User(),那么user.age顺序如下:
1)如果'age'是出现在User或者其基类的__dict__中, 且age是data descriptor,那么调用其__get__方法,否则
2)如果'age’出现在user的__dict__中, 那么直接返回user.__dict__['age'],否则
3)如果'age'出面在User或者其基类的__dict__中,
3.1)如果age是none-data descriptor,那么调用其__get__方法,否则
3.2)返回user.__dict__['age']
4)如果User有__getattr__方法, 调用__getattr__方法,否则
5)抛出AttributeError