Могу ли я удалить двойную оценку, сохранив лямбда-выражение - PullRequest
4 голосов
/ 21 марта 2019
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 ]

4 голосов
/ 21 марта 2019

Предварительная оценка:

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), ))

Здесь у вас есть живой пример

3 голосов
/ 21 марта 2019

Да, вы можете избежать двойной оценки в лямбде. Но это действительно уродливо, и вам следует избегать этого. Вот как это выглядит:

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

Легко ли это прочитать и понять? Нет, абсолютно нет. Я не собираюсь объяснять это; посмотрим, сможете ли вы понять это. Это явно не хорошее решение, так что вы должны сделать вместо этого? Вы должны использовать реальную функцию вместо лямбды.

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

Это намного легче читать и лучше.

0 голосов
/ 21 марта 2019

Я пытался сделать некоторые функции декоратора / оболочки ...

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

0 голосов
/ 21 марта 2019

Можно просто определить другую функцию:

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 голосов
/ 21 марта 2019

Возможно, вы захотите сделать это только в том случае, если ваша функция выполняется очень долго, иначе вам не следует возражать против ее запуска дважды.Вы не можете использовать список понимания .

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

...