Property的设计初衷:
【引以为戒:考虑计算成本,考虑使用方代码不更改,初次见代码心有感慨,道路长漫漫,我辈须努力】
代码复用
延迟计算
更加规范的对象属性访问管理
class X:
def __init__(self, w, h):
self.w = w
self.h = h
self.BMI = w / h ** 2
def update_w(self, w):
self.__w = w
self._update_bmi()
def _update_bmi(self):
self.BMI = self.__w / self.__h ** 2
def main():
x = X(75, 1.83)
print(x.BMI)
x.w = 74
x.w = 73
x.w = 72
print(x.BMI)
if __name__ == "__main__":
main()
源代码如上,分析:
BMI属性依旧可以被外部访问和修改
无论BMI属性是否被访问,每次w更新均会更新BMI,造成一定的计算资源浪费
改进1:
class X:
def __init__(self, w, h):
self.w = w
self.h = h
def get_bmi(self):
return self.w / self.h ** 2
def main():
x = X(75, 1.83)
print(x.get_bmi())
x.w = 74
x.w = 73
x.w = 72
print(x.get_bmi())
if __name__ == "__main__":
main()
分析:
1. 保持w和h属性可以随意更改,bmi指数仅在被访问时实时计算出结果
2. 访问BMI的方式由属性改为方法,造成一定程度上的代码修改
3. 在w更新频率高于BMI访问频率时,节省了计算资源
4. 当w未更新,却多次调用BMI指数时,造成了重复计算
使用Property
class X:
def __init__(self, w, h):
self._w = w
self._h = h
self._bmi = w / h ** 2
@property
def w(self):
return self._w
@w.setter
def w(self, value):
if value <= 0:
raise ValueError("Weight below 0 is not possible.")
self._w = value
self._bmi = self._w / self._h ** 2
@property
def BMI(self):
return self._bmi
def main():
x = X(75, 1.83)
print(x.BMI)
x.w = 74
x.w = 73
x.w = 72
print(x.BMI)
if __name__ == "__main__":
main()
分析:
1. 通过Property对象显式的控制属性的访问
2. 仅在w被更改的时候更新BMI,充分避免了重复计算
3. 很容易的增加了异常处理理,对更新属性进行预检验
4. 完美复用原始调用用代码,在调用用方不知情的情况完成功能添加