如何实现字典值的懒求值,仅首次访问时执行耗时表达式?
延迟计算字典实现方案
关于是否需要用lambda或生成器
- 你可以用
lambda来封装待执行的重计算逻辑,这是最简便的实现方式 - 不需要用到生成器,生成器适用于迭代生成多值的场景,和你需要的单次计算+缓存的需求不匹配
实现思路
核心逻辑是初始化时将每个需要延迟执行的表达式封装为无参可调用对象存入字典,第一次访问对应键时执行计算并将结果回存到字典覆盖原可调用对象,后续访问直接返回缓存后的结果即可。
代码实现
我们可以通过继承原生dict重写__getitem__方法的方式实现,和原生字典的使用习惯完全兼容:
class LazyDict(dict): def __getitem__(self, key): value = super().__getitem__(key) # 若值为可调用对象则说明还未执行计算 if callable(value): # 执行计算后回存到字典 value = value() self[key] = value return value
使用示例
初始化字典时用无参lambda封装你的重计算表达式即可:
# 初始化懒加载字典 d = LazyDict({ 'a': lambda: heavy_expression1, 'b': lambda: heavy_expression2 }) # 第一次访问才执行heavy_expression1 print(d['a']) # 后续访问直接返回缓存结果,不会重复执行计算 print(d['a'])
特殊场景兼容
如果你需要在字典中存储原生的可调用对象(不想被误执行),可以给延迟计算的条目加专属标记区分即可:
class LazyDict(dict): def __getitem__(self, key): value = super().__getitem__(key) # 只有带__lazy__标记的可调用对象才会执行计算 if isinstance(value, tuple) and len(value) == 2 and value[0] == '__lazy__': value = value[1]() self[key] = value return value # 初始化时给延迟计算条目加标记 d = LazyDict({ 'a': ('__lazy__', lambda: heavy_expression1), # 原生可调用对象不会被误执行 'my_func': lambda x: x+1 })
内容的提问来源于stack exchange,提问作者Paul R
相关产品推荐
相关产品推荐

