#python #lambda #ternary-operator
#python #лямбда #тернарный оператор
Вопрос:
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
но это не работает.
Комментарии:
1. Вы можете сохранить foo(x) в переменной tmp и использовать ее в своем коде.
Ответ №1:
Предварительная оценка:
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), ))
Здесь у вас есть живой пример
Ответ №2:
Да, вы можете избежать двойного вычисления в лямбда. Но это действительно некрасиво, и вам следует избегать этого. Вот как это выглядит:
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
Это намного проще для чтения и явно лучше.
Ответ №3:
Возможно, вы захотите сделать это, только если ваша функция выполняется очень долго, иначе вы не должны возражать против ее повторного запуска. Вы не можете использовать понимание списка.
foo = lambda x: [res if res>10 else 0 for res in [bar(x)]][0]
Комментарии:
1. я думаю, это лучше:
lambda x: next(res if res > 10 else 0 for res in (bar(x), ))
Причина в том, что вы избегаете промежуточного выделения памяти2. @Netwave Я не думаю, что промежуточный malloc уместен, даже если это зависит от функции, вы не экономите много памяти.
Ответ №4:
С таким же успехом можно просто определить другую функцию:
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)
(или переопределите bar, если вы обнаружите, что используете его только с пороговым значением)
Ответ №5:
Я попытался создать декоратор / оболочку некоторой функции…
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