Питон: Предотвращение лестниц "если"? - PullRequest
3 голосов
/ 12 февраля 2011

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

if foo:
  if bar:
    if foobar:
      if barfoo:
        if foobarfoo:
          if barfoobar:
            # And forever and ever and ever

Я не могу написать if foo and bar and foobar and ..., потому что я проверяю элементы списка значений (if foo[1] == 'bar') внутри if где-то внизу строки, и если индекс списка не существует, я получаю ошибку.

Есть ли ярлык для условной проверки таких вещей или альтернативный метод? Спасибо.

Ответы [ 7 ]

9 голосов
/ 12 февраля 2011

Я не могу написать, если foo, bar и foobar и ... потому что я вызываю элементы списка внутри if, если где-то внизу строки, и если индекс списка не существует, я получаю ошибку.

в питоне, and короткие замыкания. Если левая сторона выражения ложна, правая сторона вообще не оценивается.

foo = dict()

if 'bar' in foo and foo['bar']:
    doSomething()
5 голосов
/ 12 февраля 2011

Fail fast:

if not foo:
    return

if not foobar:
    return

и пр.

3 голосов
/ 28 сентября 2011

Там также

if all((foo, bar, foobar, barfoo, foobarfoo, barfoobar)):
    print "oh yeah"

все также будут короткими замыканиями

2 голосов
/ 12 февраля 2011

Простите, если я констатирую очевидное - но если вы проверяете много различных условий перед одной или двумя операциями, вам может быть лучше использовать try/except - особенно для этих условий (если есть)) это явные ошибки.

1 голос
/ 12 февраля 2011

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

0 голосов
/ 12 февраля 2011

Если у вас более 3–5 тестов (или более), рассмотрите возможность сохранения ваших условий в словаре, списке или кортеже. Затем проверьте эту структуру данных. Гораздо чище, чем многие индивидуальные именованные данные.

Если вы проверяете «истину» по именованному списку переменных неизвестной длины или структуре данных последовательности (например, списку или кортежу), вы можете сделать это:

def all_true(*args):
    for test in args:
        if bool(test) is False: return False 

    return True    

foo=bar=foobar=barfoo=foobarfoo=barfoobar=1

if foo:
  if bar:
    if foobar:
      if barfoo:
        if foobarfoo:
          if barfoobar:
             print "True by Stairs!"

if all_true(foo,bar,foobar,barfoo,foobarfoo,barfoobar):
    print "True by function!"

t=(foo,bar,foobar,barfoo,foobarfoo,barfoobar)

if all_true(*t): print "The tuple is true!"

l=[foo,bar,foobar,barfoo,foobarfoo,barfoobar]

if all_true(*l): print "list is true!"

bar=0
# run the same tests...

Функция all_true() будет закорочена на первое найденное ложное значение.

0 голосов
/ 12 февраля 2011

Разбейте его на несколько подкомпонентов, где это необходимо. Что касается того, где провести разделительные линии, это действительно зависит от вас. Несмотря на то, что огромная лестница условных операторов невелика, не является и массивным оператором if с таким количеством предикатов, что они заключают в себе несколько строк. Вместо этого попробуйте сгруппировать ваши условия в логические группы.

Вы могли бы написать это как:

if foo and bar and foobar:
    ...
    if barfoo and foobarfoo and barfoobar:
        ...

Я также предлагаю ввести вспомогательные методы по пути. Даже если эти вспомогательные методы вызываются только из этого кода, это нормально.

def handle_bar():
    if barfoo and foobarfoo and barfoobar:
        ...

if foo and bar and foobar:
    ...
    handle_bar()

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...