class RevealAccess: def __init__(self, init_val=None, name='var'): self.val = init_val self.name = name def __get__(self, obj, obj_type): print("Retrieving", self.name) return self.val def __set__(self, obj, val): print("updating", self.name) self.val = val class MyClass: x = RevealAccess(10, 'var "x"') y = 5 m = MyClass() print(m.x) m.x = 20 print(m.x) print(m.y) ### 运行结果 Retrieving var "x" 10 updating var "x" Retrieving var "x" 20 5
在每次查找属性时,描述符协议中的方法都由类对象的特殊方法 getattribute() 调用(注意不要和 getattr() 弄混)。也就是说,每次使用类对象.属性(或者 getattr(类对象,属性值))的调用方式时,都会隐式地调用 getattribute(),它会按照下列顺序查找该属性:
数据描述符:实现了 setter 和 getter 方法的描述符类被称为数据描述符。
非数据描述符:只实现了 getter 方法,则称为非数据描述符。