Иногда я разбиваю длинные условия в if на несколько строк. Самый очевидный способ сделать это:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Визуально это не очень привлекательно, потому что действие сочетается с условиями. Однако это естественный способ использования правильного отступа Python из 4 пробелов.
На данный момент я использую:
if ( cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Но это не очень красиво. :-)
Можете порекомендовать альтернативный способ?
Обратите внимание, что в первом примере pep8 выдаст «E129 строка с визуальным отступом с тем же отступом, что и следующая логическая строка».
Этот вопрос очень старый и имеет массу мнений, но он однозначно основан на мнениях. Формулировки «не очень привлекательный» и «не очень красивый» устанавливают критерии, согласно которым предположительно правильный ответ - это тот, который лучше всего соответствует эстетическим предпочтениям спрашивающего (то есть мнению). Я мог бы задать точно такой же вопрос и заявить, что это не дубликат, потому что мой эстетический вкус квалифицирует его как другой и приведет к другому «правильному» ответу.
@ Z4-tier: да, это основано на мнении. Но об этом спросили 12 лет назад. Тогда SO было другим местом, добрее. В последнее время накапливаются отрицательные голоса, так как стандарты SO изменились. Тем не менее, после просмотра более 1 миллиона раз, я надеюсь, что он приносит миру больше пользы, чем вреда. Я, конечно, могу видеть, как люди задаются этим же вопросом сегодня, ищут его в Google, заходят в эту дискуссию и находят полезным откалибровать свое мышление. На выбор предлагается несколько ответов, получивших большое количество голосов.
@EliBendersky полностью согласен. Это похоже на продолжающийся кризис идентичности в SO: хотя он явно не соответствует «правилам» (количество правильных ответов - свидетельство этого), столь же очевидно, что он добавляет ценности. При прочих равных, я бы предпочел работать с кем-то, кто выработал четкие и аргументированные взгляды на стиль кодирования, даже если их взгляды отличаются от моих.






Это не так сильно улучшается, но ...
allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')
if allCondsAreOK:
do_something
Интересная альтернатива. Но две лишние строчки :-)
На самом деле не будет так хорошо работать в итеративном цикле, не будет работать с функциями, которые что-то делают ... и, честно говоря - уродливо
Если вы собираетесь использовать переменную только один раз, я бы предпочел вообще не использовать переменную.
Брайан, я частично не согласен. Использование переменных для промежуточных результатов вычислений может упростить понимание кода, а на скомпилированном языке не повлияет на производительность. Вероятно, это сработало бы в python, хотя я бы вообще не стал использовать python, если бы производительность была так важна.
@MarkBaker Раньше я соглашался с тем, что вы написали, пока не прочитал Мартин Фаулер «Рефакторинг». Он приводит отличный аргумент в пользу того, что такие промежуточные переменные приносят больше вреда, чем пользы. Они препятствуют последующему рефакторингу. Отказ от них приводит к более функциональному стилю программирования, который хорошо поддается рефакторингу. Это меня удивило, но я считаю, что он прав, и с тех пор стараюсь исключить ненужные промежуточные звенья, подобные этому, из моего кода - даже если они используются более одного раза.
Кроме того, я воспользуюсь этой возможностью, чтобы заявить, что использование медленного языка программирования (например, Python) не вызывает проблем с производительностью приложений. За шесть лет, прошедших с тех пор, как я перешел с C++ и C# на Python, я не обнаружил, что мой код больше страдает от проблем с производительностью. Когда это происходит, оказывается, что это связано с неправильным выбором алгоритма или вводом-выводом. Лишь однажды за все это время я обнаружил, что производительность Python каким-либо образом невысока - при морфинге сеток вершин в каждом кадре перед их отправкой в OpenGL. В этом случае правильные и очевидные решения (используйте Numpy или шейдеры) исправили его.
Это наиболее выразительно и естественно раскладывается. Обычно условным выражениям присваивается красивое осмысленное имя, которое поможет быстро понять, когда вы вернетесь к коду через год. Я много занимаюсь рефакторингом, и очень полезно иметь сложные условные выражения, значимо «помеченные» именем переменной.
Хорошо, но почему именно CamelCase ?! :)
@LeonidShvechikov Почему не CamelCase?
Вам не нужно использовать 4 пробела во второй условной строке. Может быть, использовать:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Кроме того, не забывайте, что пробелы более гибкие, чем вы думаете:
if (
cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'
):
do_something
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Хотя оба они довольно уродливы.
Может быть, скобки потеряны (хотя Гид по стилю этого не одобряет)?
if cond1 == 'val1' and cond2 == 'val2' and \
cond3 == 'val3' and cond4 == 'val4':
do_something
По крайней мере, это дает вам некоторую дифференциацию.
Или даже:
if cond1 == 'val1' and cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
Я думаю, что предпочитаю:
if cond1 == 'val1' and \
cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
Вот Гид по стилю, который (с 2010 года) рекомендует использовать скобки.
Обратите внимание, что завершающие \ solutions не рекомендуются PEP 8. Одна из причин заключается в том, что если пробел добавлен по ошибке после \, он может не отображаться в вашем редакторе, и код станет синтаксически некорректным.
Это неправильно, в руководстве по стилю сказано: «Длинные строки можно разбить на несколько строк, заключив выражения в круглые скобки. Их следует использовать вместо использования обратной косой черты для продолжения строки». Вы можете увидеть это здесь: python.org/dev/peps/pep-0008/#maximum-line-length
@joshcartme PEP изменен на hg.python.org/peps/rev/7a48207aaab6, чтобы явно препятствовать обратному слешу. Я обновлю ответ.
Спасибо, вероятно, неплохо было бы обновить и ваши примеры, поскольку теперь они не рекомендуются. Я сам пытался в этом разобраться и был смущен несоответствием между вашим ответом и руководством по стилю (отсюда и мой комментарий). Я не просто пытался быть педантичным.
Я также предпочитаю ваш последний пример, за исключением того, что я помещаю 'и / или' в начале строк. Так как в стране Python пустое пространство - это значит, что мы не используем скобки для блоков кода, обертывание кода в скобки повторяется снова и просто выглядит уродливо IMO; PEP 8 - это всего лишь рекомендация, что означает, что вам не нужно ей следовать.
Что-то не так, если мы совместим and с if в последнем примере?
В качестве примечания к стилю я считаю, что условные выражения более читабельны, когда and и or продолжают строку, а не предыдущую строку.
Я предлагаю переместить ключевое слово and во вторую строку и сделать отступ для всех строк, содержащих условия, двумя пробелами вместо четырех:
if (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4'):
do_something
Именно так я решаю эту проблему в своем коде. Использование ключевого слова в качестве первого слова в строке делает условие более читаемым, а уменьшение количества пробелов еще больше отличает условие от действия.
Я где-то читал в Grows или Dijkstra, что размещение логического оператора в начале строки, делая его более заметным, помогло. И я занимаюсь этим с 90-х годов. И это помогает.
Обратите внимание, что Руководство по стилю рекомендует ставить условное выражение в конце строки.
Это правда, хотя я никогда с этим не соглашался. В конце концов, это всего лишь руководство.
PEP8 больше не рекомендует помещает условное выражение в конец строки.
Я предпочитаю этот стиль, когда у меня ужасно большое if-условие:
if (
expr1
and (expr2 or expr3)
and hasattr(thingy1, '__eq__')
or status= = "HappyTimes"
):
do_stuff()
else:
do_other_stuff()
+1 за отступы, где вы можете их отслеживать. Мне нравится питон, и я его много использую, но меня постоянно раздражает, что меня заставляют делать отступы именно так. Многолинейность действительно разрушает эстетику, даже если она сделана хорошо.
Обратите внимание, что наличие операторов and и or в начале строки нарушает PEP 0008, который указывает «Предпочтительное место для обрыва бинарного оператора - после оператора, а не перед ним».. Мне нравится иметь закрывающую скобку и двоеточие в отдельной строке, чтобы отделить условие if от тела (и вполне возможно сделать это, сохранив логические операторы в конце строки для соответствия PEP-0008).
по состоянию на 2016 год: For decades the recommended style was to break after binary operators. But this can hurt readability in two ways ... In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested. (стиль Кнута - начало строки с оператора).
Я прибегал к следующему в вырожденном случае, когда это просто И или ИЛИ.
if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
Он сбривает несколько персонажей и дает понять, что в этом состоянии нет никакой тонкости.
Это интересный подход. Однако не решает проблему длительных условий
Ничего страшного, если тебя не волнует короткое замыкание.
@ Константин: Дело было расширяемым, а не быстрым. Для быстрого это не идеально.
короткое замыкание не всегда происходит быстро. Хотя это не очень хорошая практика кодирования, у вас может быть существующий код вроде этого: if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Отлично, теперь ты просто случайно разрушил мир. КАК ТЫ МОГ?
Я удивлен, что за него так много голосов. Этот ответ полностью игнорирует исходный вопрос о стилизации условных выражений многострочный.
Это выражение не ленивое. Так что это не эквивалентно, если за некоторым условием защиты, возможно, не удастся.
«all» и «any» подходят для множества условий одного и того же типа case. НО они всегда оценивают все условия. Как показано в этом примере:
def c1():
print " Executed c1"
return False
def c2():
print " Executed c2"
return False
print "simple and (aborts early!)"
if c1() and c2():
pass
print
print "all (executes all :( )"
if all((c1(),c2())):
pass
print
Неверно! Они делают это только потому, что это делают ты. Попробуйте all (f () вместо f в [c1, c2]).
Я думаю, он использовал функции только в качестве примера, потому что он может легко заставить их что-то напечатать. Если мы рассматриваем серию произвольных выражений, представленных в списке для all(), тогда, если вы не собираетесь обернуть их каждое лямбда-выражением и использовать свой трюк с f(), все они будут оценены. Другими словами, Аарон: Я думаю, Андерс пытался говорить об условиях в целом, используя вызываемые объекты в качестве конкретного примера; но ваше возражение относится только к функциям.
Кто-то должен выступать за использование вертикальных пробелов здесь! :)
if ( cond1 == val1
and cond2 == val2
and cond3 == val3
):
do_stuff()
Это делает каждое условие четко видимым. Это также позволяет более четко выражать более сложные условия:
if ( cond1 == val1
or
( cond2_1 == val2_1
and cond2_2 >= val2_2
and cond2_3 != bad2_3
)
):
do_more_stuff()
Да, для ясности мы немного торгуем вертикальной недвижимостью. ИМО оно того стоит.
Это не кажется ни красивым, ни совместимым с PEP8. PEP8 говорит, что предпочтительным местом для прерывания бинарного оператора (например, and, а также or) является оператор после, а не перед ним.
@ChristopherMedrela, это объясняет причину этого? Я думаю, что размещение разрыва строки перед логическим оператором намного понятнее
Я предпочитаю это версии PEP8. Полагаю, есть элемент личного вкуса.
Ставить оператора на первое место довольно часто в мире узлов. Причина в том, что мы замечаем и читаем то, что слева, намного быстрее, чем то, что справа - по крайней мере, в западных культурах. Очень актуально в JavaScript, где забытая запятая может вызывать скрытые ошибки.
Не делай этого, пожалуйста. Это не только не PEP8, но и затрудняет определение логической операции, с которой вы связаны. Я бы завалил это, если бы он попал на мой стол через проверку кода.
@Urda Я не согласен. Размещение бинарных операторов в начале строк, а не в конце IMO делает более ясным, какова цель. Во втором примере выше, я думаю, ясно, что операнды and объединяются вместе перед тем, как or объединяется с первым условием. Но, может быть, я так думаю, потому что мне нравится Lisp ...
Что касается текущей версии PEP8, прерывание до или после бинарного оператора считается приемлемым и перед оператором считается более подходящим для нового кода.
Мне больше всего нравится этот ответ, потому что Дзен PythonReadability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.python.org/dev/peps/pep-0020
Еще несколько случайных идей для полноты картины. Если они работают на вас, используйте их. В противном случае вам, вероятно, лучше попробовать что-нибудь другое.
Вы также можете сделать это со словарем:
>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True
Этот вариант более сложный, но он может оказаться полезным:
class Klass(object):
def __init__(self, some_vars):
#initialize conditions here
def __nonzero__(self):
return (self.cond1 == 'val1' and self.cond2 == 'val2' and
self.cond3 == 'val3' and self.cond4 == 'val4')
foo = Klass()
if foo:
print "foo is true!"
else:
print "foo is false!"
Не знаю, работает ли это для вас, но это еще один вариант, который стоит рассмотреть. Вот еще один способ:
class Klass(object):
def __init__(self):
#initialize conditions here
def __eq__(self):
return (self.cond1 == 'val1' and self.cond2 == 'val2' and
self.cond3 == 'val3' and self.cond4 == 'val4')
x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
print 'x == y'
else:
print 'x!=y'
Последние два я не тестировал, но концепций должно быть достаточно, чтобы вы начали, если это то, что вы хотите использовать.
(И для записи: если это всего лишь одноразовая вещь, вам, вероятно, будет лучше использовать метод, который вы представили вначале. Если вы проводите сравнение во многих местах, эти методы могут улучшить читаемость в достаточной степени, чтобы вам не так уж плохо из-за того, что они отчасти хакерские.)
Что, если мы только вставим дополнительную пустую строку между условием и телом, а все остальное сделаем каноническим способом?
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
p.s. Я всегда использую табуляцию, а не пробелы; Я не могу настроить ...
Это было бы очень запутанным, особенно когда тело условия длинное, я думаю.
Я согласен с Эли, здесь инкапсуляция и отступы сбивают с толку длинные строки. Более того, новое правило означает, что операторы and и or должны начинаться со следующей строки.
Упакуйте свои условия в список и делайте что-л. нравиться:
if False not in Conditions:
do_something
(Я слегка изменил идентификаторы, поскольку имена с фиксированной шириной не отражают реальный код - по крайней мере, не реальный код, с которым я сталкиваюсь, - и будут противоречить удобочитаемости примера.)
if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
do_something
Это хорошо работает для «и» и «или» (важно, чтобы они были первыми во второй строке), но гораздо хуже для других длинных условий. К счастью, первое кажется более распространенным случаем, а второе часто легко переписывается с помощью временной переменной. (Обычно это не сложно, но может быть сложно или гораздо менее очевидно / читабельно сохранить короткое замыкание «и» / или «при перезаписи.)
Поскольку я нашел этот вопрос от сообщение в вашем блоге о C++, я добавлю, что мой стиль C++ идентичен:
if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
do_something
}
Вот мой очень личный подход: длинные условия (на мой взгляд) - это запах кода, который предлагает рефакторинг в функцию / метод, возвращающую логическое значение. Например:
def is_action__required(...):
return (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4')
Теперь, если бы я нашел способ заставить многострочные условия выглядеть хорошо, я бы, вероятно, удовлетворился их наличием и пропустил рефакторинг.
С другой стороны, их возмущение в моем эстетическом восприятии является стимулом для рефакторинга.
Поэтому я пришел к выводу, что условия с несколькими линиями должны выглядеть некрасиво, и это стимул избегать их.
Я удивлен, что не вижу своего предпочтительного решения,
if (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4'):
do_something
Поскольку and является ключевым словом, он выделяется моим редактором и существенно отличается от do_something под ним.
Но линия продолжения по-прежнему не отличается от следующей логической строки ...
Обратите внимание, что это нарушение PEP 0008 («Предпочтительное место для обрыва бинарного оператора - после оператора, а не перед ним»). Неважно, заботитесь ли вы, конечно, решать вам.
Кстати, это больше не мое любимое решение. ;)
Добавляя к тому, что сказал @krawyoti ... Длинные условия пахнут, потому что их трудно читать и трудно понять. Использование функции или переменной делает код более понятным. В Python я предпочитаю использовать вертикальное пространство, заключать скобки и помещать логические операторы в начало каждой строки, чтобы выражения не выглядели «плавающими».
conditions_met = (
cond1 == 'val1'
and cond2 == 'val2'
and cond3 == 'val3'
and cond4 == 'val4'
)
if conditions_met:
do_something
Если условия необходимо оценивать более одного раза, как в цикле while, то лучше всего использовать локальную функцию.
В дополнение к этому вы можете объявить функцию или лямбду, чтобы возвращать ваше истинное значение false, а не создавать дополнительную переменную.
@Techdragon, если условия должны быть где-то еще, то для их помещения в лямбда-блок потребуется имя лямбда-блока, чтобы на него можно было ссылаться позже в условии if. Если лямбда будет названа, почему это, в конце концов, не обычная функция? Мне лично нравится это сокращенное логическое выражение.
Я согласен, поэтому я обычно использую функцию в большинстве случаев как для улучшения читаемости, так и для облегчения мысленного переваривания при просмотре, чтобы понять поток управления программой. Я упоминаю лямбда, чтобы гарантировать, что вариант «меньшего размера» также присутствует в случае, если люди особенно озабочены пространством.
Это круто. К сожалению, если я включу Path(input).is_dir() или Path(input).is_file() в предложение переменных, я получу TypeError: 'bool' object is not callable.
Я обнаружил, что когда у меня длинные условия, у меня часто бывает короткое тело кода. В этом случае я просто делаю двойной отступ в теле, таким образом:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
@qarma, не хотите ли вы расшириться? Это, безусловно, лучше, чем использовать символы продолжения строки, которые не рекомендуются PEP 8.
На самом деле это действительный случай для продолжения строки. IMPO Круглые скобки обозначают кортеж или вызов функции. Использование OP очень похоже на C, я предпочитаю синтаксис Python, когда это возможно. Однако я признаю, что \ не приветствуется всеми.
if cond1 == 'val1' and \
cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
или, если это яснее:
if cond1 == 'val1'\
and cond2 == 'val2'\
and cond3 == 'val3'\
and cond4 == 'val4':
do_something
Нет причин, по которым в этом случае отступ должен быть кратен 4, например см. «Выровнено по открывающему разделителю»:
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation.
Руководство Google также предоставляет пример сложного состояния, который соответствует «наиболее очевидному способу сделать это», как указано в OP. Хотя в руководстве нет явной поддержки такого форматирования длинных «если».
Лично мне нравится придавать смысл длинным операторам if. Мне пришлось бы искать подходящий пример по коду, но вот первый пример, который приходит на ум: допустим, я случайно столкнулся с какой-то причудливой логикой, когда я хочу отобразить определенную страницу в зависимости от многих переменных.
Английский: «Если вошедший в систему пользователь НЕ является преподавателем-администратором, а является обычным преподавателем, а не самим учеником ...»
if not user.isAdmin() and user.isTeacher() and not user.isStudent():
doSomething()
Конечно, это может выглядеть нормально, но читать эти операторы if - это большая работа. Как насчет того, чтобы присвоить логику ярлыку, который имеет смысл. «Метка» - это на самом деле имя переменной:
displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
showTeacherPanel()
Это может показаться глупым, но у вас может быть еще одно условие, при котором вы хотите отображать другой элемент ТОЛЬКО тогда и только тогда, когда вы показываете панель учителя ИЛИ если пользователь по умолчанию имеет доступ к этой другой конкретной панели:
if displayTeacherPanel or user.canSeeSpecialPanel():
showSpecialPanel()
Попробуйте написать приведенное выше условие без использования переменных для хранения и маркировки вашей логики, и вы не только получите очень беспорядочный, трудно читаемый логический оператор, но и просто повторите себя. Хотя есть разумные исключения, помните: не повторяйтесь (СУХОЙ).
Что я обычно делаю:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'
):
do_something
таким образом закрывающая скобка и двоеточие визуально обозначают конец нашего условия.
Почти правильно; PEP 8 теперь рекомендует взломать до and или or.
Вот еще один подход:
cond_list = ['cond1 == "val1"','cond2= = "val2"','cond3= = "val3"','cond4= = "val4"']
if all([eval(i) for i in cond_list]):
do something
Это также упрощает добавление другого условия без изменения оператора if, просто добавляя другое условие в список:
cond_list.append('cond5= = "val5"')
Вот что я делаю. Помните, что «all» и «any» допускают итерацию, поэтому я просто помещаю длинное условие в список и позволяю «all» выполнять работу.
condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']
if all(condition):
do_something
Плохой случай, если в cond4 вы хотите проверить функцию или если cond2 является свойством cond1. Пример условий: object is not None and object.param == 5 and object.is_running()
Простой и понятный, также проходит проверки pep8:
if (
cond1 and
cond2
):
print("Hello World!")
В последнее время я предпочитаю функции all и any, так как я редко смешиваю сравнения And и Or, это хорошо работает и имеет дополнительное преимущество в виде раннего отказа с пониманием генераторов:
if all([
cond1,
cond2,
]):
print("Hello World!")
Просто не забудьте передать одну итерацию! Передача N-аргументов неверна.
Примечание: any похож на многие сравнения or, all похож на многие сравнения and.
Это прекрасно сочетается с пониманием генератора, например:
# Check if every string in a list contains a substring:
my_list = [
'a substring is like a string',
'another substring'
]
if all('substring' in item for item in my_list):
print("Hello World!")
# or
if all(
'substring' in item
for item in my_list
):
print("Hello World!")
Подробнее на: генератор понимания
Я также должен отметить, что стандартная конфигурация pylint требует отступа от входа в продолжение строки в if; что меня отговорило от использования этой схемы.
Я тоже изо всех сил пытался найти достойный способ сделать это, поэтому мне просто пришла в голову идея (не серебряная пуля, поскольку это в основном вопрос вкуса).
if bool(condition1 and
condition2 and
...
conditionN):
foo()
bar()
Я нахожу несколько преимуществ в этом решении по сравнению с другими, которые я видел, а именно: вы получаете ровно 4 дополнительных места для отступа (bool), позволяя всем условиям выстраиваться вертикально, а тело оператора if может быть с отступом в ясный (иш) способ. Это также сохраняет преимущества короткого замыкания логических операторов, но, конечно, добавляет накладные расходы на вызов функции, который в основном ничего не делает. Вы могли бы возразить (справедливо), что здесь можно использовать любую функцию, возвращающую свой аргумент, вместо bool, но, как я уже сказал, это всего лишь идея и, в конечном счете, дело вкуса.
Достаточно забавно, когда я писал это и думал о «проблеме», мне пришла в голову идея еще один, которая устраняет накладные расходы на вызов функции. Почему бы не указать, что мы собираемся ввести сложное условие, с помощью дополнительных пар круглых скобок? Скажем, еще 2, чтобы дать хороший отступ в 2 пробела для подусловий относительно тела оператора if. Пример:
if (((foo and
bar and
frob and
ninja_bear))):
do_stuff()
Мне это нравится, потому что, когда вы смотрите на это, в вашей голове сразу же звонит колокольчик: "Эй, здесь происходит сложная вещь!". Да, я знаю, что скобки не улучшают читаемость, но эти условия должны появляться достаточно редко, и когда они действительно появляются, вам все равно придется остановиться и внимательно прочитать их (потому что они сложный).
Во всяком случае, еще два предложения, которых я здесь не видел. Надеюсь, это кому-то поможет :)
Обычно я использую:
if ((cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')):
do_something()
Похоже, стоит процитировать PEP 0008 (официальное руководство по стилю Python), поскольку в нем довольно подробно комментируется эта проблема:
When the conditional part of an
if-statement is long enough to require that it be written across multiple lines, it's worth noting that the combination of a two character keyword (i.e.if), plus a single space, plus an opening parenthesis creates a natural 4-space indent for the subsequent lines of the multiline conditional. This can produce a visual conflict with the indented suite of code nested inside theif-statement, which would also naturally be indented to 4 spaces. This PEP takes no explicit position on how (or whether) to further visually distinguish such conditional lines from the nested suite inside theif-statement. Acceptable options in this situation include, but are not limited to:# No extra indentation. if (this_is_one_thing and that_is_another_thing): do_something() # Add a comment, which will provide some distinction in editors # supporting syntax highlighting. if (this_is_one_thing and that_is_another_thing): # Since both conditions are true, we can frobnicate. do_something() # Add some extra indentation on the conditional continuation line. if (this_is_one_thing and that_is_another_thing): do_something()
Обратите внимание на «не ограничено» в приведенной выше цитате; Помимо подходов, предложенных в руководстве по стилю, приемлемы и некоторые из подходов, предложенных в других ответах на этот вопрос.
+1 для PEP8. Этот должен следует принять, поскольку это (практически говоря) официальное руководство по стилю Python.
Также стоит подчеркнуть, что PEP8 явно заявляет о своей позиции как Этот PEP не занимает явной позиции относительно того, как (и нужно ли) дополнительно визуально отличать такие условные строки от вложенного набора внутри if -statement. Допустимые варианты в этой ситуации включают, но не ограничиваются: ... (вырезано) Итак, хватит спорить, выбирайте то, что вам нравится!
если наше условие if & an else должно выполнять внутри себя несколько операторов, чем мы можем написать, как показано ниже. Каждый раз, когда у нас есть пример if else с одним выражением внутри него.
Спасибо, это сработало для меня.
#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''
if numberOfArgument == 5:
weblogic_username = sys.argv[1]
weblogic_password = sys.argv[2]
weblogic_admin_server_host =sys.argv[3]
weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
weblogic_username = raw_input("Enter Weblogic user Name")
weblogic_password = raw_input('Enter Weblogic user Password')
weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf
Вы можете разделить его на две строки
total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
do_something()
Или даже добавляйте по одному условию за раз. Таким образом, по крайней мере, он отделяет беспорядок от if.
Я знаю, что эта ветка устарела, но у меня есть код Python 2.7, а PyCharm (4.5) все еще жалуется на этот случай:
if foo is not None:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
# some comment about do_something
do_something
Даже с предупреждением PEP8 «строка с визуальным отступом и тем же отступом, что и следующая логическая строка», фактический код полностью в порядке? Это не «чрезмерный отступ»?
... бывают случаи, когда мне хотелось бы, чтобы Python укусил пулю и просто оставил фигурные скобки. Интересно, сколько ошибок было случайно введено за эти годы из-за случайного неправильного отступа ...
Все респонденты, которые также предоставляют несколько условий для оператора if, столь же уродливы, как и представленная проблема. Вы не решите эту проблему, сделав то же самое ...
Даже ответ PEP 0008 отталкивает.
Вот гораздо более читаемый подход
condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
pass
Хотите, чтобы я съел свои слова? Убедите меня, что вам нужны несколько условий, и я буквально распечатаю это и съем для вашего развлечения.
это действительно очень удобный способ использования нескольких условий :) не знаю, почему у него нет большего количества голосов :), есть ли какие-то оговорки?
@SaulCruz на самом деле нет Мало того, что переменную условия не нужно повторять, вы также экономите на множестве дубликатов проверки каждого значения, это просто помещает только значения в массив и позволяет движку выполнять свою (оптимизированную) работу в проверяю состояние для вас
@Stoff Спасибо, что удалили мой комментарий. Я хотел указать, что ваш подход не отвечает на вопрос ОП. Предоставленный вами код нельзя применить к коду, указанному в вопросе. Если вы думаете иначе, вам следует добавить код OP, отформатированный в соответствии с вашим подходом, чтобы доказать свою точку зрения.
Это не общепринятый ответ, однако это явно альтернативный подход (другие согласны). ТАК поощрял альтернативные ответы, так что же именно за аргумент? Четко сформулируйте свой вопрос, возможно, подумайте о том, чтобы открыть свой вопрос, если вам требуется должное внимание. P.s. Я не модификатор SO, я не могу удалять комментарии
Я думаю, что решение @zkanda было бы хорошим с небольшим поворотом. Если бы у вас были свои условия и значения в их собственных списках, вы могли бы использовать понимание списка для сравнения, что сделало бы вещи немного более общими для добавления пар условие / значение.
conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
# do something
Если бы я действительно хотел жестко закодировать такой оператор, я бы написал его так для удобочитаемости:
if (condition1==value1) and (condition2==value2) and \
(condition3==value3) and (condition4==value4):
И просто выбросить другое решение с Оператор iand:
proceed = True
for c, v in zip(conditions, values):
proceed &= c==v
if proceed:
# do something
Ради интереса: all(map(eq, have, expected)). (с from operator import eq)
Простите мою глупость, но бывает, что я не так хорошо разбираюсь в #Python, как кто-либо из вас здесь, но бывает, что я нашел нечто подобное при написании сценариев моих собственных объектов в моделировании 3D BIM, поэтому я адаптирую свой алгоритм к что из питона.
Проблема, которую я здесь обнаружил, двусторонняя:
Чтобы обойти все эти проблемы, ваш скрипт должен выглядеть так:
param_Val01 = Value 01 #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04 # and ... etc
conditions = 0 # this is a value placeholder
########
Add script that if true will make:
conditions = conditions + param_Val01 #value of placeholder is updated
########
### repeat as needed
if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
do something
Плюсы этого метода:
Скрипт читабельный.
Скрипт легко поддерживать.
Надеюсь, это поможет вам всем
Если ваш редактор использует пакет Python pep8, чтобы определить, когда следует предупреждать о нарушениях PEP8, вам придется либо отключить ошибку E125, либо найти решение форматирования, которое удовлетворяет критериям пакета
pep8. Пакетpep8Выпуск # 126 предназначен для исправления пакета, чтобы строго следовать спецификации PEP8. Обсуждение проблемы включает некоторые предложения по стилю, которые также можно найти здесь.