2009-10-11 6 views
9
def isBig(x): 
    if x > 4: 
     return 'apple' 
    else: 
     return 'orange' 

Это работает:Как назначить переменную в IF, а затем вернуть ее. (Python)

if isBig(y): return isBig(y) 

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

if fruit = isBig(y): return fruit 

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

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

+6

Для чего нужен однострочный вкладыш? Программы не улучшаются, потому что у них меньше строк. –

+0

То же, что http://stackoverflow.com/questions/1513436/what-should-i-use-instead-of-assignment-in-an-expression-in-python/1513987#1513987 – PaulMcG

+2

У вас есть 100 из них? Вы бы не стали писать парсер, не так ли? См. Этот список (http://nedbatchelder.com/text/python-parsers.html) с веб-сайта Ned Batchelder. – PaulMcG

ответ

16

Я вижу, кто-то уже указывал на мой старый «назначить и установить» Cookbook рецепт, который сводится в простейшем варианте для:

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) 

если None является правильным возвращаемым значением, если не предикат не удовлетворен И т.д.

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

0

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

0

Проблемы заключается в том, что операция присваивания не может быть оценена как имеющая логическое значение. Оператор 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 
+0

Я не знаю, потому что это имеет смысл. Я проголосовал за вас: – TIMEX

+4

(Я не спустил вниз, но) Отсутствие логического возврата не является _cause_ невозможности использовать его в инструкции 'if()'. Оба этих ограничения - _side-effects_ языка, определяющего назначение как выражение, а не выражение. –

2

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

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

fruit = isBig(y) 
if fruit: return fruit 

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

+2

Я не считаю версию более или менее читаемой, но, возможно, это из опыта. Кроме того, IMHO больше _consistent_, чтобы сделать его выражением, поскольку '=' выглядит (и анализируется как интерпретаторами, так и людьми) как оператор (неявное выражение), а не функция (неявный оператор, хотя это isn ' t технически верно). –

+0

Откровенно говоря, вы не всегда можете использовать язык, который хотите для проекта, что делает его одним из наименее полезных ответов, которые я когда-либо видел. Если бы я мог проголосовать вас дюжину раз, я бы это сделал. – Rabbit

+1

Кролик, если вам требуется использовать какой-либо конкретный язык по любой причине, вы должны использовать его правильно. Пытаться обуздать другие языковые конструкции - глупая идея. Я видел такие причудливые вещи, как '#define begin {' в коде C, потому что программисты Pascal не хотели адаптироваться. Такое поведение делает код бесполезным в _both_ языках. – paxdiablo

8

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

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

tmp = isBig(y) 
if tmp: return tmp 

Действительно ли это намного хуже?

+2

Спасибо. Кстати, когда у вас таких 100, это намного хуже :) – TIMEX

+5

Когда у вас есть 100 таких строк, это немного похоже на то, что ваше решение не оптимально, но я не могу говорить, не зная, что вы делаю. –

+1

По крайней мере, кормите свои тестовые примеры в список и перебирайте его, чтобы не писать все так. –

-3
print "apple" if x > 4 else "orange" 
+0

Это не имеет никакого отношения к вопросу. –

Смежные вопросы