通过描述符自定制@property的功能
# 通过描述符自定制@property的功能 # 原始通过@property实现的功能:将类中定义的函数属性,通过装饰器@property将其封闭成数据属性 class Room: def __init__(self, name, width, length): self.name = name self.width = width self.length = length @property def area(self): return self.width * self.length r1 = Room('厨房', 10, 4) print(r1.area) # 通过描述符与装饰器自定制@property的功能 class Lazyproperty: # 定义描述符的类 def __init__(self, func): # 初始化时接收传入的方法进行保存 self.func = func def __get__(self, instance, owner): if instance is None: # 解决直接用类调用属性时传不了实例而报错的问题 return self res = self.func(instance) setattr(instance, self.func.__name__, res) # 将res放入实例的字典中,如果下次再调用,根据优先级实例属性高于非数据描述符,实例的属性字典中有就直接从实例的属性字典中找了 return res # 返回实例对象调用父类方法的结果,instance代表实例 class Room2: def __init__(self, name, width, length): self.name = name self.width = width self.length = length @Lazyproperty # area=Lazyproperty(area) 使用装饰器的这一步就相当于对area属性指定了描述符,给Room2添加了一个类属性 def area(self): return self.width * self.length r2 = Room('厨房', 10, 4) # 实例调用area print(r2.area) # 从r2中先找有没有area属性,没有从父类Room2中找,找到后发现是非数据描述符,就触发了__get__方法 # 类调用area print(Room2.area) # 由于__get__方法的接收参数需要一个实例,这里是用类调用的,所以会传None过去,因此会报错