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

问题描述 投票:4回答:5
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

但这不起作用。

python lambda ternary-operator
5个回答
4
投票

Preevaluate:

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


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

这更容易阅读,显然更好。


0
投票

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

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


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)

(或重新定义条,如果您发现自己只使用阈值)


0
投票

我试过make一些函数decorator / wrapper ...

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

© www.soinside.com 2019 - 2024. All rights reserved.