发布于2020-03-10 20:51 阅读(1292) 评论(0) 点赞(16) 收藏(0)
在某些场景中,我们可能更希望系统执行的高效性,在某些属性不被访问时,其不存在,当被访问时才会生成空间,另外生成后会将结果保存在缓存中,下次调用该属性会直接去取缓存中的值,而不是冗余地再去执行很多代码得到新的值。此过程,称之为惰性求值。
实例代码进行解释:
class lazyproperty:
def __init__(self,func):
self.func = func
print(self.func.__name__)
def __get__(self, instance, owner):
print(self,instance,owner)
if instance is None:
return self
else:
value = self.func(instance)
setattr(instance,self.func.__name__,value)#为对象设置属性值,当属性不存在时创建该属性
#或者:#instance.__dict__[self.func.__name__] = value
return value
#注意:此处并没有定义__set__()方法
import math
class Circle:
def __init__(self,radius):
self.radius = radius
@lazyproperty
def area(self):
print('computing area ...')
return self.radius ** 2 * math.pi
@lazyproperty
def perimetter(self):
print('compiting perimeter ...')
return 2*math.pi*self.radius
c = Circle(2.0)
print('1:',vars(c))#1: {'radius': 2.0} 底层字典中并没有area的属性
print(c.area)#当访问的数据不在底层的实例字典(instance.__dict__)中时,才会调用__get__();
# 此时实例c的底层字典通过上一行得知并没有area这个属性
#与c.area = 4.0 直接的区别是该赋值会直接将属性加入字典中。
#而惰性求值只有在访问该属性时才会将属性插入底层字典,不访问面积时会节约空间
print('2:',vars(c))#2: {'radius': 2.0, 'area': 12.566370614359172} 底层字典中才有area的属性
print(c.area)#该次打印由于已经由上次的c.area的调用导致将area的属性插入了字典中,
# 所以本次打印会直接在底层字典中寻找这个属性值,而不会再去调用area().
c.area = 25
print(c.area)#此时这种属性是可变的属性area: 4.0 -> 25
#通过如下方法可以是属性变为不可被修改的属性:
def lazyProperty(func):
name = '_lazy_'+func.__name__
print(name)
@property #相当于:lazy.getter
def lazy(self):
if hasattr(self,name):
getattr(self,name)
else:
value = func(self)
setattr(self,name,value)
print(name)
return value #相当于上述的__get__()
#注意:此处并未设置@lazy.setter,所以并不能对属性值进行设置!!!如果设置了,如下:
# 情景二:
@lazy.setter
def lazy(self,value):
setattr(self,name,value)
print(value)
return lazy
import math
class Circle:
def __init__(self,radius):
self.radius = radius
@lazyProperty
def area(self):
print('computing area ...')
return self.radius ** 2 * math.pi
@lazyProperty
def perimetter(self):
print('compiting perimeter ...')
return 2*math.pi*self.radius
c = Circle(2.0)
print(c.area)
'''
computing area ...
_lazy_area
12.566370614359172
'''
c.area = 28
'''
#如果不释放上述情景二的代码:
#则属性值不可被修改:
Traceback (most recent call last):
File "F:/PycharmProjects/class_obj/class_one.py", line 249, in <module>
c.area = 28
AttributeError: can't set attribute
Process finished with exit code 1
'''
'''
#如果释放掉上述情景二的注释:
#则会得到:
28
'''
代码来源于书籍,但是代码中的注释为自己的理解,望重点看下注释内容。
作者:我Lovepython
链接:https://www.pythonheidong.com/blog/article/251634/d024d7521f2fc97256b3/
来源:python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!