Стилізація багаторядкових умов у операторах "якщо"? [зачинено]


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
Якщо ваш редактор використовує пакет pep8 Python, щоб виявити, коли попереджати про порушення PEP8 , вам доведеться або відключити помилку E125, або знайти рішення форматування, яке задовольняє pep8критеріям пакета. Випуск pep8пакету № 126 полягає в тому, щоб виправити пакет, щоб суворо дотримуватися специфікації PEP8. Обговорення цього питання включає деякі стильові пропозиції, які також можна побачити тут.
akaihola

1
Зверніть увагу, що в першому прикладі pep8 викине "E129 візуально відрізану лінію з тим же відступом, що і наступний логічний рядок".
Тейлор Едмістон

Це питання дуже старе і має точку зору, але воно однозначно базується на думках. Мова "не дуже приваблива" та "не дуже симпатична" викладає критерії, що нібито правильна відповідь - це найкраща відповідність естетичним уподобанням запитуючих (тобто думка). Я міг би задати абсолютно те саме питання і стверджувати, що це не дублікат, оскільки мій естетичний смак кваліфікує його як різний, і призведе до іншої "правильної" відповіді.
Z4-ярус

@ Z4-рівень: так, це засновано на думці. Але це запитали 12 років тому. Так тоді було інше, добріше місце. Останнім часом він накопичує низові канали, оскільки змінилися стандарти ПС. І все-таки переглянувши> 1 мільйон разів, я сподіваюся, що це робить більше користі, ніж шкоди у світі. Я, безумовно, можу побачити людей, які цікавляться тим же питанням сьогодні, погугливши його, поклавшись на цю дискусію і вважаючи корисним калібрувати своє мислення. Є кілька високоголосних відповідей на вибір.
Елі Бендерський

@EliBendersky повністю згоден. Начебто ТА має кризу ідентичності, що триває: хоча вона, очевидно, не відповідає «правилам» (кількість обґрунтованих відповідей є свідченням цього), це так само ясно, що це додає значення. При рівних умовах я б швидше працював з тим, у кого склалися чіткі та аргументовані погляди на стиль кодування, навіть якщо їх погляди відрізнялися від моїх.
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, щоб явно відмовити від нахилів . Я оновлю відповідь.
Harley Holcombe

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
Я здивований, що це так багато відгуків. Ця відповідь повністю ігнорує оригінальне запитання про стилізацію багаторядкових умов.
Пшемек 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 (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

2
+1 для зберігання відступів, де ви можете відстежувати їх. Мені подобається python і дуже його використовую, але мене постійно дратує те, що його змушують відступати саме так. Багаторядковість, якщо справді руйнує естетичне, навіть якщо зроблено добре.
Могутній

4
Зауважте, що наявність вашого 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.(стиль Knuth - це почати лінію з оператором)
коуберт

27

Ось моя дуже особиста думка: довгі умови - це (на мій погляд) кодовий запах, який пропонує рефакторинг на булеву функцію / метод повернення. Наприклад:

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

Тепер, якби я знайшов спосіб зробити так, щоб багаторядкові умови виглядали добре, я, мабуть, знайшов би задоволення від наявності їх і пропустив би рефакторинг.

З іншого боку, їх збурення моє естетичне почуття виступає стимулом до рефакторингу.

Отже, мій висновок полягає в тому, що умови декількох ліній повинні виглядати негарно, і це стимул уникати їх.


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

Саме так я вирішую цю проблему у своєму коді. Наявність ключового слова в якості першого слова в рядку робить умову набагато легшою для читання, а зменшення кількості пробілів ще більше відрізняє умову від дії.


9
Я десь читав або в Гріса, або в Джікстра, що поміщення логічного оператора в передній частині рядка - зробити більш помітним - допомогло. І я цим займаюся з 90-х. І це допомагає.
С.Лотт

7
Зауважте, що Керівництво стилем рекомендує ставити умовне в кінці рядка.
Harley Holcombe

3
Це правда, хоча я ніколи з цим не погоджувався. Адже це лише путівник.
DzinX

8
PEP8 більше не рекомендує ставити умовне в кінці рядка.
Сорен Бьорнстад

14

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

Коли умовна частина ifакредитива є достатньо довгою, щоб вимагати її написання через кілька рядків, варто зазначити, що комбінація ключового слова з двома символами (тобто if), плюс один пробіл, плюс дужки, що відкриваються, створює природний 4- простірний відступ для наступних рядків багаторядного умовного. Це може призвести до візуального конфлікту з ifвідрізним набором коду, вкладеним всередині- Statement, який, природно, також буде розрізаний на 4 пробіли. Цей ПЕП не займає явної позиції щодо того, як (або чи) надалі візуально відрізняти такі умовні лінії від вкладеного набору всередині 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.
Michael - Де Clay Shirky

2
Також варто підкреслити, що PEP8 чітко висловлює свою позицію, оскільки цей PEP не займає явної позиції щодо того, як (або чи) надалі візуально відрізняти такі умовні лінії від вкладеного набору всередині if-Statement. Допустимі варіанти в цій ситуації включають, але не обмежуються цим: ... (відрізано). Отже, перестаньте сперечатися, займіться тим, що вам подобається!
RayLuo

7

Ось що я роблю, пам’ятайте, що «все» та «будь-яке» приймає ітерабельний, тому я просто поклав довгий стан у список і дозволю «всім» виконати роботу.

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

if all(condition):
   do_something

4

Я здивований, що не бачу вподобаного рішення,

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

Оскільки andце ключове слово, воно виділяється моїм редактором і виглядає достатньо відмінним від того, що робиться під ним.


Але лінія продовження все ще не відрізняється від наступної логічної лінії ...
Кріс Медрела

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, якщо умови мають бути деінде, то для їх розміщення в лямбда-блоку буде потрібно назвати блок лямбда, щоб він міг посилатися пізніше в умові 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()

Спробуйте написати вищевказану умову, не використовуючи змінні для зберігання та маркування вашої логіки, і ви не лише закінчитеся з дуже брудним, важким для читання логічним висловлюванням, але ви також просто повторили себе. Хоча існують розумні винятки, пам’ятайте: не повторюйте себе (DRY).


3

"всі" та "будь-які" приємні для багатьох умов одного типу випадків. АЛЕ вони завжди оцінюють усі умови. Як показано в цьому прикладі:

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функціям, оскільки я рідко змішую І і Або порівняння, це добре працює, і має додаткову перевагу «Невдалий ранній» із розумінням генераторів:

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

Більше про: розуміння генератора


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

таким чином фіксатор та товста кишка візуально позначають кінець нашого стану.


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

Хочете, щоб я їв свої слова? Переконайте, що вам потрібні багатозагальні умови, і я буквально роздрукую це і з'їм це для вашої розваги.


це дійсно дуже охайний спосіб виконання багатозастережних умов :) Не знаю, чому у нього немає більше голосів :), чи є якісь застереження?
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

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.


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 кусав кулю і просто пішов з фігурними дужками. Цікаво, скільки помилок було випадково впроваджено за ці роки через випадкове неправильне відступ ...


0

Упакуйте свої умови в список, а потім зробіть що-небудь. подібно до:

if False not in Conditions:
    do_something

0

Я вважаю, що коли я маю довгі умови, у мене часто є короткий корпус коду. У такому випадку я просто подвійно відступаю тіло, таким чином:

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

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 також надає приклад складної умови , яка відповідає "найбільш очевидним способом цього зробити", як згадується в ОП. Хоча посібник прямо не виступає за форматування довгих “якщо” так.
Антон Строгонов

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


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. Не потрібно багаторівневих умов

Сподіваюся, це допоможе вам усім

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.