class Lazyproperty: def __init__(self, func): self.func = func def __get__(self, instance, owner): print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()') if instance is None: return self # 如果没有传进实例,那就返回area -- > area=Lazyproperty(area) else: print('--->') value = self.func(instance) # 是描述符帮我们实现了自动传值 setattr(instance, self.func.__name__, value) # 计算一次就缓存到实例的属性字典中 return value class Room: def __init__(self, name, width, length): self.name = name self.width = width self.length = length @Lazyproperty # area=Lazyproperty(area) 相当于'定义了一个类属性,即描述符' def area(self): return self.width * self.length r1 = Room('alex', 1, 1) print(r1.area) # 先从自己的属性字典找,没有再去类的中找,然后出发了area的__get__方法 print(r1.area) # 先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算
如果给Lazyproperty加了__set__,那就会变成数据描述符,数据描述符的优先级是大于实例属性的,这样就会去调用数据描述符,缓存就失效了。