Стилизировать многострочные условия в операторах if? [закрыто]

677

Иногда я разбиваю длинные условия в ifs на несколько строк. Наиболее очевидный способ сделать это:

  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

Но это не очень красиво. :-)

Можете ли вы порекомендовать альтернативный способ?

Эли Бендерский
источник
2
Если ваш редактор использует пакет Python pep8 , чтобы определить, когда следует предупреждать о нарушениях PEP8 , вам придется либо отключить ошибку E125, либо найти решение для форматирования, которое удовлетворяет pep8критериям пакета. В pep8ПАКЕТЕ в выпуске № 126 о фиксации пакета строго следовать PEP8 спецификации. Обсуждение проблемы включает в себя некоторые предложения по стилю, которые также можно увидеть здесь.
akaihola
1
Обратите внимание, что в первом примере pep8 выдаст «строку с визуальным отступом E129 с тем же отступом, что и у следующей логической строки».
Тейлор Эдмистон
Этот вопрос очень старый и имеет массу взглядов, но он однозначно основан на мнении. Язык «не очень привлекателен» и «не очень симпатичен» определяет критерии того, что предположительно правильный ответ - это тот, который лучше всего соответствует эстетическим предпочтениям спрашивающих (то есть мнению). Я мог бы задать точно такой же вопрос и утверждать, что это не дубликат, потому что мой эстетический вкус квалифицирует его как другой и приведет к другому «правильному» ответу.
Z4-й уровень
@ Z4-уровень: да, это основано на мнении. Но это спросили 12 лет назад. Так что тогда было другое, добрее место. В последнее время накапливаются отрицательные отзывы, так как стандарты SO изменились. Тем не менее, будучи просмотренным> 1 млн раз, я надеюсь, что это приносит больше пользы, чем вреда в мире. Я, конечно, могу видеть, что люди задаются вопросом об одном и том же вопросе сегодня, гуглят его, садятся на эту дискуссию и считают ее полезной для калибровки своего мышления. Есть несколько высоко оцененных ответов на выбор.
Эли Бендерский
@EliBendersky полностью согласен. Это похоже на то, что у SO продолжается кризис идентичности: хотя он явно не соответствует «правилам» (количество действительных ответов является свидетельством этого), точно так же ясно, что он добавляет ценность. При прочих равных условиях я бы предпочел работать с кем-то, кто разработал четкие и аргументированные взгляды на стиль кодирования, даже если их взгляды отличались от моих.
Z4-й уровень

Ответы:

750

Вам не нужно использовать 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 года) рекомендует использовать скобки.

Харли Холкомб
источник
45
Обратите внимание, что конечные \ решения не рекомендуются PEP 8. Одна из причин заключается в том, что если пробел добавлен по ошибке после \, он может не отображаться в вашем редакторе, и код становится синтаксически некорректным.
Эрик О Лебиго
14
Это неправильно, руководство по стилю говорит: «Длинные строки можно разбить на несколько строк, заключив выражения в скобки. Они должны использоваться вместо использования обратной косой черты для продолжения строки». Вы можете увидеть это здесь: python.org/dev/peps/pep-0008/#maximum-line-length
joshcartme
8
@joshcartme PEP был изменен на hg.python.org/peps/rev/7a48207aaab6 для явного предотвращения обратной косой черты. Я обновлю ответ.
Харли Холкомб
3
Спасибо, вероятно, это хорошая идея, чтобы обновить ваши примеры, так как они сейчас не рекомендуются. Я пытался понять это сам и был смущен несоответствием между вашим ответом и руководством по стилю (отсюда и мой комментарий). Я не просто пытался быть педантичным.
joshcartme
3
PEP 8 теперь препятствует нарушению после andи if.
virtualxtc
124

Я прибег к следующему в вырожденном случае, когда это просто И или ИЛИ.

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

Он бреет нескольких персонажей и дает понять, что в этом нет тонкости.

С. Лотт
источник
4
Это интересный подход. Однако проблема длинных условий не решается
Эли Бендерский,
20
Это нормально, если вас не волнует короткое замыкание.
Константин
63
короткометражка не всегда о быстром. Хотя это и не хорошо кодирования практики, вы можете иметь существующий код , как это: if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Отлично, теперь вы просто уничтожили мир случайно. КАК ТЫ МОГ?
Аарон
4
Я удивлен, что это имеет так много голосов. Этот ответ полностью игнорирует первоначальный вопрос о стилизации многострочных условных выражений.
Przemek D
2
Это выражение не ленивое. Так что это не эквивалентно, если за каким-то охраняющим условием последует возможное невыполнение.
Евгений-яркий
57

Кто-то должен защищать использование вертикальных пробелов здесь! :)

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

Да, мы продаем немного вертикальной недвижимости для ясности. Стоит того ИМО.

Кевин Литтл
источник
19
Это не кажется ни красивым, ни PEP8-совместимым. PEP8 говорит, что предпочтительное место для разбиения вокруг бинарного оператора (например, andа также or) находится после оператора, а не перед ним.
Крис Медрела
7
@ChristopherMedrela это говорит обоснование этого? я думаю, что размещение разрыва строки перед логическим оператором намного понятнее
Norill Tempest
4
Поставить оператор на первое место довольно часто в мире узлов. Смысл в том, что мы замечаем и читаем материал слева намного быстрее, чем материал справа - по крайней мере, в западных культурах. Очень актуально в JavaScript, где забытая запятая может привести к тихим ошибкам.
Tomekwi
11
Не делай этого, пожалуйста. Это не только не PEP8затрудняет определение логической операции, с которой вы соединяетесь. Я бы провалил это, если бы он пришел к моему столу через проверку кода.
Урда
11
Начиная с текущей версии PEP8, разрыв до или после двоичного оператора считается приемлемым , а перед оператором считается лучшим для нового кода.
Сорен Бьорнстад
31

Я предпочитаю этот стиль, когда у меня ужасно большое условие if:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()
Deestan
источник
2
+1 для хранения отступов, где вы можете отслеживать их. Я люблю python и очень часто им пользуюсь, но меня постоянно раздражает то, что меня заставляют делать отступы именно так. Многострочный, если действительно разрушает эстетику, даже когда сделано хорошо.
Могучий
4
Обратите внимание, что наличие операторов your andи orв начале строки нарушает PEP 0008 , который гласит: «Предпочтительное место для разбивки двоичного оператора - после оператора, а не перед ним». , Мне нравится иметь закрывающую скобку и двоеточие в отдельной строке, чтобы отделить условие if от тела, хотя (и это вполне возможно сделать, оставив ваши логические операторы в конце строки для соответствия PEP-0008).
Марк Амери
8
с 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.(стиль Кнута - начало строки с оператором).
Cowbert
27

Вот мое очень личное мнение: длинные условия - это (на мой взгляд) запах кода, который предполагает рефакторинг в булево-возвращаемую функцию / метод. Например:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

Теперь, если бы я нашел способ, чтобы многострочные условия выглядели хорошо, я, вероятно, был бы доволен их наличием и пропустил рефакторинг.

С другой стороны, их нарушение моего эстетического ощущения служит стимулом для рефакторинга.

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

krawyoti
источник
23

Это не так сильно улучшится, но ...

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')

if allCondsAreOK:
   do_something
Федерико А. Рампони
источник
1
Интересная альтернатива. Но 2 дополнительные строки :-)
Эли Бендерский
Не будет действительно хорошо работать в итеративном цикле, не будет работать с функциями, которые что-то делают ... и быть справедливым - безобразно
Мез
9
Брайан, я частично не согласен. Использование переменных для промежуточных результатов вычислений может облегчить понимание кода, и на скомпилированном языке это не повлияет на производительность. Это, вероятно, сработало бы в python, хотя я бы вообще не использовал python, если бы производительность была так важна.
Марк Бейкер
1
@MarkBaker Я имел обыкновение соглашаться с тем, что вы написали, пока я не прочитал Мартина Фаулерса «Рефакторинг». Он приводит превосходный аргумент, что такие промежуточные переменные приносят больше вреда, чем пользы. Они препятствуют последующему рефакторингу. Обойтись без них приводит к более функциональному стилю программирования, который хорошо поддается рефакторингу. Это удивило меня, но я считаю, что он прав, и с тех пор стремился исключить ненужные промежуточные звенья, подобные этому, из моего кода - даже если они используются более одного раза.
Джонатан Хартли
2
Хорошо, но почему CamelCase ?! :)
Леонид Швечиков
19

Я предлагаю переместить andключевое слово на вторую строку и сделать отступ для всех строк, содержащих условия, с двумя пробелами вместо четырех:

if (cond1 == 'val1' and cond2 == 'val2'
  and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Именно так я решаю эту проблему в своем коде. Наличие ключевого слова в качестве первого слова в строке делает условие намного более читабельным, а сокращение количества пробелов еще больше отличает условие от действия.

DzinX
источник
9
Я где-то читал в «Гризе» или «Джикстре», что размещение логического оператора в начале строки - делая его более заметным - помогло. И я занимаюсь этим с 90-х годов. И это помогает.
S.Lott
7
Обратите внимание, что в Руководстве по стилю рекомендуется поместить условное обозначение в конец строки.
Харли Холкомб
3
Это правда, хотя я никогда не соглашался с этим в этом. В конце концов, это всего лишь руководство.
DzinX
8
PEP8 больше не рекомендует помещать условное в конец строки.
Сорен Бьорнстад
14

Кажется, стоит цитировать PEP 0008 (официальное руководство по стилю Python), так как он комментирует эту проблему в скромной длине:

Когда условная часть if-статажа достаточно длинна, чтобы требовать ее записи в несколько строк, стоит отметить, что комбинация двухсимвольного ключевого слова (т. Е. if), Плюс один пробел и открывающая скобка создают естественную 4- отступ для последующих строк условного многострочного Это может привести к визуальному конфликту с набором кода с отступом, вложенным в if-statement, который также естественно будет иметь отступ в 4 пробела. Этот PEP не занимает явной позиции о том, как (или следует) дополнительно визуально отличать такие условные строки от вложенного набора внутри if-статмента. Приемлемые варианты в этой ситуации включают, но не ограничиваются:

# 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.
Майкл - Где Клэй Ширки?
2
Также стоит подчеркнуть, что PEP8 явно заявляет о своей позиции, так как This PEP не занимает явной позиции о том, как (или следует) дополнительно визуально отличать такие условные строки от вложенного набора внутри if-состояния. Приемлемые варианты в этой ситуации включают, но не ограничиваются: ... (отрезано) Итак, перестаньте спорить, иди с тем, что тебе нравится!
RayLuo
7

Вот что я делаю, помните, что «все» и «любой» принимает итерируемое, поэтому я просто помещаю длинное условие в список и позволяю «всем» делать работу.

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something
zkanda
источник
4

Я удивлен, что не вижу своего предпочтительного решения,

if (cond1 == 'val1' and cond2 == 'val2'
    and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Поскольку andэто ключевое слово, оно выделяется моим редактором и выглядит достаточно отличающимся от do_something под ним.

Мариус Гедминас
источник
Но линия продолжения все еще не отличается от следующей логической линии ...
Крис Медрела
1
Обратите внимание, что это нарушение PEP 0008 ( «Предпочтительное место для разрыва двоичного оператора - после оператора, а не перед ним» ). Разве вы заботитесь, конечно, решать вам.
Марк Амери
1
Между прочим, это больше не мое предпочтительное решение. ;)
Мариус Гедминас
4

Добавляя к тому, что сказал @krawyoti ... Длинные условия пахнут, потому что они трудны для чтения и трудны для понимания. Использование функции или переменной делает код более понятным. В Python я предпочитаю использовать вертикальное пространство, заключать в скобки и размещать логические операторы в начале каждой строки, чтобы выражения не выглядели как «плавающие».

conditions_met = (
    cond1 == 'val1' 
    and cond2 == 'val2' 
    and cond3 == 'val3' 
    and cond4 == 'val4'
    )
if conditions_met:
    do_something

Если условия необходимо оценивать более одного раза, как в whileцикле, то лучше использовать локальную функцию.

апалала
источник
1
В дополнение к этому вы можете объявить функцию или лямбду, которые возвращают ваше истинное ложное значение, в отличие от создания дополнительной переменной.
Techdragon
@Techdragon, если условия должны быть в другом месте, то для помещения их в лямбда-блок потребуется, чтобы лямбда-блок был назван так, чтобы на него можно было ссылаться позже в условии if. Если лямбда будет названа, почему она, а не обычная функция, в конце концов? Мне лично нравится это сокращенное логическое выражение.
Шри Кадимисетти
Я согласен, именно поэтому я обычно использовал бы функцию в большинстве случаев как для улучшения читабельности, так и для облегчения умственного переваривания при скимминге, чтобы понять процесс управления программой. Я упоминаю лямбду, чтобы гарантировать, что «меньший» вариант также присутствует в случае, если люди особенно космически сознательны.
Techdragon
4

Лично мне нравится добавлять смысл в длинные операторы if. Мне пришлось бы искать в коде, чтобы найти подходящий пример, но вот первый пример, который приходит на ум: допустим, я случайно натолкнулся на какую-то странную логику, где я хочу отобразить определенную страницу в зависимости от многих переменных.

Английский: «Если вошедший в систему пользователь НЕ является учителем-администратором, а просто обычным учителем и не является самим студентом ...»

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

Конечно, это может выглядеть хорошо, но читать их, если заявления много работы. Как насчет того, чтобы мы присвоили логику метке, которая имеет смысл. «Метка» - это имя переменной:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

Это может показаться глупым, но у вас может быть еще одно условие, когда вы ТОЛЬКО хотите отображать другой элемент, если и только если вы отображаете панель учителя ИЛИ, если у пользователя есть доступ к этой другой конкретной панели по умолчанию:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

Попробуйте написать вышеупомянутое условие, не используя переменные для хранения и маркировки вашей логики, и вы не только получите очень грязное, трудно читаемое логическое утверждение, но вы также просто повторили себя. Хотя есть разумные исключения, помните: не повторяйте себя (СУХОЙ).

rgenito
источник
3

«all» и «any» хороши для многих условий одного типа. НО они всегда оценивают все условия. Как показано в этом примере:

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
Андерс Вальденборг
источник
5
Некорректное! Они делают только потому, что вы делаете. Попробуйте все (f () для f в [c1, c2]).
Хабнабит
2
Я думаю, что он использовал функции только в качестве примера, потому что он может легко заставить их что-то напечатать. Если мы рассмотрим ряд произвольных выражений, представленных в списке на all()то время, если вы не собираетесь обернуть их каждое в лямбду и использовать свой f()трюк, все они будут оценены. Другими словами, Аарон: я думаю, что Андерс пытался говорить об условиях в целом, используя в качестве конкретного примера вызываемые объекты; но ваш ответ относится только к функциям.
Брэндон Родс
3

(Я слегка изменил идентификаторы, так как имена с фиксированной шириной не представляют реальный код - по крайней мере, реальный код, с которым я сталкиваюсь - и будут полагаться на читаемость примера.)

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
}
Фред Нурк
источник
3

Простой и простой, также проходит проверку pep8:

if (
    cond1 and
    cond2
):
    print("Hello World!")

В последнее время я предпочитая allи anyфункции, так как я редко смешиваются И и Или сравнения это работает хорошо, и имеет дополнительное преимущество При отсутствии Early с генераторами понимания:

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!")

Больше на: понимание генератора

ThorSummoner
источник
1
Я также должен указать, что конфигурация запаса Pylint требует отступа в начале строки в if; который отговорил меня от использования этой схемы.
ThorSummoner
2

Что если мы вставим только дополнительную пустую строку между условием и телом и сделаем все остальное каноническим способом?

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):

    do_something

PS Я всегда использую табуляции, а не пробелы; Я не могу точно настроить ...

Федерико А. Рампони
источник
3
Это было бы очень запутанным, особенно когда тело условного символа длинное, я думаю.
Эли Бендерский
Я согласен с Эли, инкапсуляция и отступы здесь сбивают с толку для длинных строк. Кроме того, новое правило является то , что andи orзаявления должны начать на следующей строке
virtualxtc
2

Что я обычно делаю, это:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

таким образом закрывающая скобка и двоеточие визуально обозначают конец нашего состояния.

tomekwi
источник
1
Почти правильно; PEP 8 теперь рекомендует прерывать до andили or.
virtualxtc
2

Все респонденты, которые также предоставляют мультиусловия для утверждения if, столь же безобразны, как и представленная проблема. Вы не решаете эту проблему, делая то же самое ..

Даже ответ PEP 0008 отталкивающий.

Вот гораздо более читаемый подход

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

Хочешь, чтобы я съел мои слова? Убедите меня, что вам нужны мультиусловия, и я буквально напечатаю это и съест это для вашего удовольствия.

Stoff
источник
это действительно очень аккуратный способ выполнения мультиусловий :) не знаю, почему у него нет больше голосов :), есть какие-то предостережения?
dim_user
@SaulCruz там на самом деле нет. Не только не нужно повторять условную переменную, вы также экономите на множестве дубликатов проверки каждого значения, это просто помещает только значения в массив и позволяет движку выполнять свою (оптимизированную) работу в проверка состояния для вас
Stoff
@ Stoff Спасибо за удаление моего комментария. Я хотел бы отметить, что ваш подход не отвечает на вопрос ОП. Предоставленный вами код не может быть применен к коду в вопросе. Если вы думаете иначе, вы должны добавить код OP, переформатированный вашим подходом, чтобы доказать свою точку зрения.
Jeyekomon
Это не принятый ответ, однако это явно альтернативный подход (другие согласны). ТАК поощряются альтернативные ответы, так в чем конкретно аргумент? Будьте ясны в своем вопросе, возможно, подумайте над тем, чтобы открыть свой вопрос, если вам требуется должное внимание. Ps Я не SO мод, я не могу удалить комментарии
Stoff
2

Я думаю, что решение @ 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
ryanjdillon
источник
1
Просто для удовольствия all(map(eq, have, expected)). (с from operator import eq)
Габриэль Гарсиа
1

Просто несколько других случайных идей для полноты картины. Если они работают на вас, используйте их. В противном случае вам, вероятно, лучше попробовать что-то другое.

Вы также можете сделать это с помощью словаря:

>>> 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'

Последние два я не проверял, но концепций должно быть достаточно, чтобы вы начали, если вы хотите этого.

(И для справки: если это всего лишь один раз, возможно, вам лучше использовать метод, который вы представили сначала. Если вы проводите сравнение во многих местах, эти методы могут улучшить читабельность, достаточную для Вы не чувствуете себя так плохо по поводу того, что они отчасти хакеры.)

Джейсон Бейкер
источник
1

Я изо всех сил пытался найти достойный способ сделать это, поэтому я просто пришел с идеей (не серебряная пуля, так как это в основном дело вкуса).

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

Мне это нравится, потому что, когда вы смотрите на это, в вашей голове немедленно звонит колокольчик, говоря: «Эй, здесь происходит сложная вещь!» , Да, я знаю, что круглые скобки не помогают читабельности, но эти условия должны появляться достаточно редко, и когда они все-таки появятся, вам в любом случае придется остановиться и прочитать их осторожно (потому что они сложные ).

Во всяком случае, еще два предложения, которые я не видел здесь. Надеюсь, это поможет кому-то :)

Эль ниндзя Трепадор
источник
1

Вы можете разбить его на две строки

total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
    do_something()

Или даже добавить по одному условию за раз. Таким образом, по крайней мере, это отделяет беспорядок от if.

SarcasticSully
источник
1

Я знаю, что эта ветка старая, но у меня есть немного кода 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 укусил пулю и просто ушел с фигурными скобками. Интересно, сколько ошибок было случайно введено за эти годы из-за случайного неверного отступа ...

SMGreenfield
источник
0

Упакуйте свои условия в список, затем сделайте что-нибудь. подобно:

if False not in Conditions:
    do_something
psihodelia
источник
0

Я нахожу, что когда у меня длинные условия, у меня часто короткое тело кода. В этом случае я просто делаю двойной отступ в теле, таким образом:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
        do_something
xorsyst
источник
1
@qarma, ты хочешь расширить? Это, безусловно, лучше, чем использование символов продолжения строки, которые рекомендуются PEP 8
xorsyst
На самом деле это правильный случай продолжения строки. Скобки IMPO обозначают кортеж или вызов функции. Использование OP очень похоже на C, я предпочитаю синтаксис Python, когда это возможно. Я признаю, что \ не всеобщее одобрение все же.
Дима Тиснек
0
  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. Хотя руководство явно не рекомендует форматировать длинные слова «если».
Антон Строгонов
0

Вот еще один подход:

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"')
user1487551
источник
0

Я обычно использую:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()
Артур Гаспар
источник
0

Если наше условие 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
Лаксман Г
источник
0

Прошу прощения за мою нелюбовь, но бывает, что я не так хорошо разбираюсь в #Python, как кто-либо из вас здесь, но бывает, что я обнаружил нечто подобное при написании сценариев своих собственных объектов в 3D BIM-моделировании, поэтому я адаптирую свой алгоритм к что из питона.

Проблема, которую я нахожу здесь, является двусторонней:

  1. Значения мои кажутся чуждыми для тех, кто может попытаться расшифровать сценарий.
  2. Обслуживание кода будет стоить дорого, если эти значения будут изменены (наиболее вероятные) или если будут добавлены новые условия (нарушенная схема)

Чтобы обойти все эти проблемы, ваш скрипт должен идти так

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

Плюсы этого метода:

  1. Скрипт читабелен.

  2. Сценарий может быть легко поддерживается.

  3. условие - операция сравнения 1 с суммой значений, которая представляет желаемые условия.
  4. Нет необходимости в многоуровневых условиях

Надеюсь, это поможет вам всем

Надер Белал
источник