我可以在保留lambda表达式的同时删除双重评估吗

时间:2019-03-21 08:21:29

标签: python lambda ternary-operator

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

但这不起作用。

5 个答案:

答案 0 :(得分:4)

预先评估:

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

答案 1 :(得分:3)

是的,您可以避免在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

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

答案 2 :(得分:0)

仅当您的函数执行时间很长时,才可能要执行此操作,否则您不必介意两次运行它。您不能使用列表理解

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

答案 3 :(得分:0)

也可以只定义另一个功能:

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)

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

答案 4 :(得分:0)

我试着做一些函数装饰器/包装器...

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