Как назначить переменную в условии IF, а затем вернуть ее?

def isBig(x):
   if x > 4: 
       return 'apple'
   else: 
       return 'orange'

Это работает:

if isBig(y): return isBig(y)

Это НЕ работает:

if fruit = isBig(y): return fruit

Почему 2-й не работает!? Я хочу 1-лайнер. Кроме того, 1-й вызовет функцию TWICE.

Как сделать это 1 лайнер, не вызывая функцию дважды?

Ответ 1

Я вижу, что кто-то еще указал на мой старый рецепт "рецепт и набор" поваренной книги, который сводится к простейшей версии:

class Holder(object):
   def set(self, value):
     self.value = value
     return value
   def get(self):
     return self.value

h = Holder()

...

if h.set(isBig(y)): return h.get()

Однако это предназначалось в основном для упрощения транслитерации между Python и языками, где назначение напрямую поддерживается в if или while. Если у вас есть "сотни" такой проверки и возврата в каскаде, гораздо лучше сделать что-то совершенно другое:

hundreds = isBig, isSmall, isJuicy, isBlah, ...

for predicate in hundreds:
  result = predicate(y)
  if result: return result

или даже что-то вроде

return next(x for x in (f(y) for f in hundreds) if x)

если это нормально, чтобы получить исключение StopIteration, если предикат не выполняется, или

return next((x for x in (f(y) for f in hundreds) if x)), None)

if None - это правильное возвращаемое значение, когда предикат не выполняется и т.д.

Почти всегда, используя (или даже желая;), трюк/не-идиома Holder является "дизайнерским запахом", который предлагает искать другой и более питоновский подход - тот случай, когда Holder оправданным является именно тот особый случай, для которого я его разработал, т.е. случай, когда вы хотите поддерживать близкое соответствие между кодом Python и некоторым не-Python (вы транслитерируете эталонный алгоритм в Python и хотите, чтобы он работал сначала, прежде чем реорганизовывать его в более питоническую форму, или вы пишете Python в качестве прототипа, который будет транслитерирован в С++, С#, Java и т.д., когда он эффективно работает).

Ответ 2

Один лайнер не работает, потому что в Python присваивание (fruit = isBig(y)) является выражением, а не выражением. В C, С++, Perl и бесчисленных других языках это выражение, и вы можете поместить его в if или while или что угодно, но не на Python, потому что создатели Python думали, что это слишком легко злоупотреблять (или злоупотреблять), чтобы написать "умный" код (например, вы пытаетесь).

Кроме того, ваш пример довольно глупый. isBig() всегда будет оцениваться как true, так как единственная строка, которая является ложью, является пустой строкой (""), поэтому ваш оператор if бесполезен в этом случае. Я предполагаю, что просто упрощение того, что вы пытаетесь сделать. Просто сделайте следующее:

tmp = isBig(y)
if tmp: return tmp

Неужели это намного хуже?

Ответ 3

Начиная с Python 3.8 и введением выражений присваивания (PEP 572) (оператор :=), теперь можно фиксировать значение условия (isBig(y)) как переменную (x) в Для того, чтобы повторно использовать его в теле условия:

if x := isBig(y): return x

Ответ 4

Если вы хотите ввести код в PHP (или C), введите код в нем. Не пытайтесь заставить свои методы на другой язык.

Одним из основных принципов, лежащих в основе Python (на мой взгляд), является его читаемость. Вы должны использовать:

fruit = isBig(y)
if fruit: return fruit

Я также должен упомянуть, что использование isXXX() очень странно; он обычно используется для возврата булевых значений. Особенно в этом случае, когда вы используете его в инструкции IF.

Ответ 5

Это не работает из-за намеренного дизайна языка, но вы можете использовать этот трюк, чтобы обойти это решение

Ответ 6

Проблема заключается в том, что операция присваивания не может быть оценена как имеющая логическое значение. Оператор if полагается на возможность оценивать логическое значение. Например,

>>> fruit = 'apple'
>>> bool(fruit = 'apple')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/Users/jem/<ipython console> in <module>()

TypeError: 'fruit' is an invalid keyword argument for this function
>>> bool('a')
True

Ответ 7

Вы можете использовать генератор:

def ensure(x):
    if x: yield x

for fruit in ensure(isBig(y)):
    return fruit

Ответ 8

print "apple" if x > 4 else "orange"