【问题标题】:Lazy evaluation of dict values?对dict值的懒惰评估?
【发布时间】:2021-12-25 01:58:50
【问题描述】:

假设我有以下字典d={'a': heavy_expression1, 'b': heavy_expression2}

如何包装表达式,以便在访问它们后对其进行评估,之后不再执行评估?

d['a'] # only here heavy_expression1 is executed
d['a'] # no execution here, already calculated

我需要使用lambda 还是生成器?

【问题讨论】:

  • 您可以将global 变量内的heavy_expression1 传递为executed = True 并将其用作if condition
  • 为什么不使用带有cached properties 的类而不是裸字典?
  • 快速想法:将字典的所有相关值初始化为None,然后通过处理函数查询字典,该处理函数将None替换为运行时遇到的评估表达式。表达式将存在于处理函数中,而不是字典。
  • 这两个heavy_expression真的不同,还是它们涉及到关键,只是不同?
  • 为什么要在这里使用字典?

标签: python python-3.x lazy-evaluation


【解决方案1】:

带有 lambda 的版本:

class LazyDict(dict):
    def __init__(self, lazies):
        self.lazies = lazies
    def __missing__(self, key):
        value = self[key] = self.lazies[key]()
        return value

d = LazyDict({'a': lambda: print('heavy_expression1') or 1,
              'b': lambda: print('heavy_expression2') or 2})
print(d['a'])
print(d['a'])
print(d['b'])
print(d['b'])

输出:

heavy_expression1
1
1
heavy_expression2
2
2

【讨论】:

    【解决方案2】:

    另一种方法是中断子类中的__getitem__ 方法并在那里进行缓存:

    class LazyDict(dict):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.cache = {}
    
        def __getitem__(self, item):
            if item in self.cache:
                return self.cache[item]
            result = super().__getitem__(item)()
    
            self.cache[item] = result
            return result
    

    这是带有函数的测试用例:(如果您不想定义函数,lambda 非常适合这里)

    def heavy_expresion1():
        print('heavy expression1 is calculated')
        return 10
    
    def heavy_expresion2():
        print('heavy expression2 is calculated')
        return 20
    
    d = LazyDict({'a': heavy_expresion1, 'b': heavy_expresion2})
    print(d)
    
    print(d['a'])
    print(d['a'])
    
    print(d['b'])
    print(d['b'])
    

    输出:

    {'a': <function heavy_expresion1 at 0x000001AFE783ED30>, 'b': <function heavy_expresion2 at 0x000001AFE8036940>}
    heavy expression1 is calculated
    10
    10
    heavy expression2 is calculated
    20
    20
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-07
      • 1970-01-01
      • 2015-09-06
      • 2016-12-14
      • 2018-04-01
      • 2018-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多