Python设计模式-惰性计算/延迟计算(Lazy Evaluation)
惰性计算/延迟计算(Lazy Evaluation)
目的:类的某个属性来自于一个复杂的耗时的计算,但并不是每次都会调用。通过lazy evaluation模式,可以使该值只在真正需要读取的时候才进行一次计算
示例
import functools
class lazy_property:
'''一种 lazy property类装饰器'''
def __init__(self, function):
self.function = function
functools.update_wrapper(self, function)
def __get__(self, obj, type_):
if obj is None:
return self
val = self.function(obj)
obj.__dict__[self.function.__name__] = val
return val
def lazy_property2(fn):
'''一种 lazy propety函数装饰器'''
attr = "_lazy__" + fn.__name__
@property
def _lazy_property(self):
if not hasattr(self, attr):
setattr(self, attr, fn(self))
return getattr(self, attr)
return _lazy_property
class Person:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
self.call_count2 = 0
# 这个装饰器,使Person.relatives可以当做属性来调用,并且,只有在第一次调用的时候会进行一次计算,调用前并不使用计算资源。从从而达到提高性能的目的。
@lazy_property
def relatives(self):
# Get all relatives, let's assume that it costs much time.
relatives = "Many relatives."
return relatives
@lazy_property2
def parents(self):
self.call_count2 += 1
return "Father and mother"
# 调用
if __name__ == '__main__':
Jhon = Person('Jhon', 'Coder')
# 调用 Jhon.relatives之前,relatves函数并没有真正执行
sorted(Jhon.__dict__.items())
# 预期输出 [('call_count2', 0), ('name', 'Jhon'), ('occupation', 'Coder')]
Jhon.relatives
# 预期输出 'Many relatives.'
# 调用 Jhon.relatives之后,relatves函数已执行并将结果保存到同名属性中
sorted(Jhon.__dict__.items())
# 预期输出 [('call_count2', 0), ..., ('relatives', 'Many relatives.')]
# 调用 Jhon.parents之后,该函数被执行,并将结果保存到_lazy__parents中
Jhon.parents
# 预期输出 'Father and mother'
sorted(Jhon.__dict__.items())
# 预期输出 [('_lazy__parents', 'Father and mother'), ('call_count2', 1), ..., ('relatives', 'Many relatives.')]
# 从 call_count2 == 1 可以看出,parents被调用了一次
# 再次调用 Jhon.parents,parents函数不会被执行,仅仅是从已有的_lazy__parents中取出结果。
Jhon.parents
# 预期输出 'Father and mother'
sorted(Jhon.__dict__.items())
Jhon.call_count2
# 预期输出 1
ref
https://blog.csdn.net/qq_23981335/article/details/102474702
https://en.wikipedia.org/wiki/Lazy_evaluation
bottle
https://github.com/bottlepy/bottle/blob/cafc15419cbb4a6cb748e6ecdccf92893bb25ce5/bottle.py#L270
django
https://github.com/django/django/blob/ffd18732f3ee9e6f0374aff9ccf350d85187fac2/django/utils/functional.py#L19
pip
https://github.com/pypa/pip/blob/cb75cca785629e15efb46c35903827b3eae13481/pip/utils/init.py#L821
pyramid
https://github.com/Pylons/pyramid/blob/7909e9503cdfc6f6e84d2c7ace1d3c03ca1d8b73/pyramid/decorator.py#L4
werkzeug
https://github.com/pallets/werkzeug/blob/5a2bf35441006d832ab1ed5a31963cbc366c99ac/werkzeug/utils.py#L35
本文来自博客园,作者:坦先生的AI资料室,转载请注明原文链接:https://www.cnblogs.com/yushengchn/p/16478449.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现