【问题标题】:Can I remove double evaluation whilst keeping lambda expression我可以在保留 lambda 表达式的同时删除双重评估吗
【发布时间】:2019-08-12 01:27:12
【问题描述】:
def bar(x):
    # some expensive calculation
    <snip>

foo = lambda(x): bar(x) if bar(x) > 10 else 0

但是在这里我计算了 foo 两次。有没有办法仍然把它写成一个衬里但避免双重评估。我试过了

foo = lambda(x): v if (v = bar(x)) > 10 else 0

但这不起作用。

【问题讨论】:

  • 您可以将 foo(x) 存储在一个变量 tmp 中并在您的代码中使用它。

标签: python lambda ternary-operator


【解决方案1】:

我尝试过制作一些函数装饰器/包装器...

def funcdec(func):
    def inner(x):
        if func(x) > 10:
           return func(x)
        else:
           return 0

然后

@funcdec
def bar(x):
    return x * 2

那我试试....:

foo = lambda x: bar(x)

给我结果:

foo(2)

返回 0 和

foo(10)

返回 20

【讨论】:

    【解决方案2】:

    还不如定义另一个函数:

    def bar(x):
        # some expensive calculation
        <snip>
    
    def bar_threshold(x,t):
        y = bar(x)
        return y if y>t else 0
    
    foo = lambda x: bar_threshold(x,10)
    

    (或重新定义栏,如果您发现自己仅在阈值上使用它)

    【讨论】:

      【解决方案3】:

      预评估:

      foo    = lambda(x): x if x > 10 else 0
      result = foo(bar(x))
      

      在这里你可以看到你的代码有什么相似之处:

      lambda (x): foo(x) if foo(x) > 10 else 0 == (lambda(x): x if x > 10 else 0)(foo(x))
      

      除非您创建某种可变状态对象或其他一些奇怪的技巧,否则您所寻求的是不可能的。

      @Alakazam 的答案既棘手又聪明,使用它需要您自担风险。最好使用迭代器和next 来避免额外的中间列表:

      lambda x: next(res if res > 10 else 0 for res in (bar(x), ))
      

      这里有live example

      【讨论】:

        【解决方案4】:

        是的,您可以避免在 lambda 中进行双重评估。但它真的很难看,你应该避免它。下面是它的外观:

        foo = lambda x: next(b if b > 10 else 0 for b in [bar(x)])
        

        这是否易于阅读和理解?不,绝对不是。我不打算解释它;看看你能不能弄清楚。这显然不是一个好的解决方案,那么您应该怎么做呢?您应该使用真正的函数而不是 lambda。

        def foo(x):
            b = bar(x)
            return b if b > 10 else 0
        

        这更容易阅读,而且明显更好。

        【讨论】:

          【解决方案5】:

          您可能只想在您的函数执行时间很长时才这样做,否则您不应该介意运行它两次。您不能使用列表推导

          foo = lambda x: [res if res&gt;10 else 0 for res in [bar(x)]][0]

          【讨论】:

          • 我认为这个更好:lambda x: next(res if res &gt; 10 else 0 for res in (bar(x), )),原因是您避免了中间内存分配
          • @Netwave 我不认为中间 malloc 是相关的,即使它取决于函数,你也不会节省很多内存。
          猜你喜欢
          • 2012-03-30
          • 1970-01-01
          • 2016-04-25
          • 2011-08-08
          • 1970-01-01
          • 2010-09-09
          • 1970-01-01
          • 1970-01-01
          • 2016-03-18
          相关资源
          最近更新 更多