【问题标题】:Deferring function call in argument in python 3python 3中的参数中延迟函数调用
【发布时间】:2020-06-05 14:29:50
【问题描述】:

我正在尝试使用固定字典将各种缓存添加到昂贵的函数中。像这样的:

def func(arg):
    if arg in precomputed:
        return precomputed[arg]
    else:
        return expensive_function(arg)

现在如果我可以使用dict.get() 默认值来做这样的事情会更干净一点:

def func(arg):
    return precomputed.get(arg, expensive_function(arg))

问题是,expensive_function() 运行无论precomputed.get() 是否成功,所以我们得到了所有的脂肪而不是任何味道。

有没有办法可以在这里推迟对expensive_function() 的调用,以便仅在precomputed_get() 失败时调用它?

【问题讨论】:

  • 我认为最 Pythonic 的方式是 try: return pre[arg] except KeyError: return exp_fun(arg)... 为什么它需要单线?
  • 根据输入,lru_cache 装饰器可能是一种替代解决方案。
  • @deceze 为什么 try-catch 如此 Pythonic?我已经看到它在其他情况下被推荐,但我有点坚持其他语言的“尽可能避免陷入错误处理代码”的心态。不会影响性能吗?
  • 您可能想阅读“Idiomatic Python: EAFP versus LBYL
  • 我的意思是,其他问题中的解决方案并不能真正帮助您 - 但我可以告诉您,经过 8 年的经验,您最初拥有的简单易读的 if 语句是首先是最好的方法:)

标签: python python-3.x function deferred-execution


【解决方案1】:

如果您正在寻找清洁度,我建议使用库而不是重新发明轮子:

from functools import lru_cache

@lru_cache
def expensive_function(arg):
    # do expensive thing
    pass

现在所有对expensive_function 的调用都被记录下来了,你可以在不处理缓存的情况下调用它。 (如果担心内存消耗,甚至可以限制缓存大小。)

要回答字面上的问题,Python 无法创建像 Haskell 或 Scheme 那样懒惰地评估其参数的函数或宏。在 Python 中延迟计算的唯一方法是将其包装在函数或生成器中。它将比您的原始代码更少,而不是更多,可读性。

【讨论】:

    【解决方案2】:
    def func(arg):
        result = precomputed[arg] if arg in precomputed else expensive_function(arg)
        return result
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-07
      • 2016-03-22
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多