"еще" считается вредным для Python?

В ответе (S.Lott) на вопрос о инструкции Python try...else:

Собственно, даже в случае if-утверждения иначе: можно злоупотреблять в поистине страшной способы создания ошибок, которые очень сложны найти. [...]

Подумайте дважды о другом:. это вообще проблема. Избегайте этого, кроме в выражении if и даже тогда рассмотрите документирование else- чтобы сделать его явным.

Это широко распространенное мнение? Является else считается вредным?

Конечно, вы можете написать с ним путающий код, но это верно для любой другой конструкции языка. Даже Python for...else мне кажется очень удобным (менее того, для try...else).

Ответ 1

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

Ответ 2

Нет, это не вредно, это необходимо.

Всегда должен быть оператор catch-all. Все коммутаторы должны иметь значение по умолчанию. Все соответствия шаблонов в языке ML должны иметь значение по умолчанию.

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

Если вы действительно боитесь, что неизвестные ошибки остаются незаметными в операторах else, неужели так сложно поднять исключение?

Ответ 3

Говорить, что другое считается вредным, немного похоже на то, что переменные или классы вредны. Черт возьми, ему даже нравится говорить, что goto вреден. Конечно, вещи могут быть использованы неправильно. Но в какой-то момент вам просто нужно доверять программистам быть взрослыми и быть достаточно умными, чтобы не делать этого.

В чем дело: если вы не хотите что-то использовать, потому что ответ на SO или сообщение в блоге или даже знаменитая статья от Dijkstra вам не нужно, вам нужно подумать, правильно ли программирование профессия для вас.

Ответ 4

Я бы не сказал, что это вредно, но бывают случаи, когда инструкция else может вызвать у вас неприятности. Например, если вам нужно выполнить некоторую обработку на основе входного значения, и есть только два допустимых входных значения. Только проверка на наличие ошибки может привести к ошибке. например:

The only valid inputs are 1 and 2:

if(input == 1)
{
   //do processing
   ...
}
else
{
   //do processing 
   ...
}

В этом случае использование else позволит обрабатывать все значения, отличные от 1, когда это должно быть только для значений 1 и 2.

Ответ 5

Для меня вся концепция некоторых популярных языковых конструкций, являющихся неотъемлемо плохими, просто неверна. Даже goto имеет свое место. Я видел очень читаемый, поддерживаемый код такими, как Уолтер Брайт и Линус Торвальдс, который его использует. Гораздо лучше просто учить программистов, чтобы читаемость учитывалась и использовала здравый смысл, чем произвольно объявлять определенные конструкции "вредными".

Ответ 6

Если вы пишете:

if foo:
    # ...
elif bar:
    # ...
# ...

тогда читателю может быть интересно: что если ни foo, ни bar не верны? Возможно, вы знаете, по вашему пониманию кода, что это должно быть так, что либо foo, либо bar. Я бы предпочел посмотреть:

if foo:
    # ...
else:
    # at this point, we know that bar is true.
    # ...
# ...

или

if foo:
    # ...
else:
    assert bar
    # ...
# ...

Это дает читателю понять, как вы ожидаете контроля над потоком, не требуя от читателя глубокого знания того, откуда foo и bar.

(в исходном случае вы все равно можете написать комментарий, объясняющий, что происходит, но я думаю, что тогда я задался вопросом: "Почему бы просто не использовать предложение else:?))

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

Что действительно касается большинства вещей в языках программирования, действительно: -)

Ответ 7

Else наиболее полезен при документировании предположений о коде. Это гарантирует, что вы продумали обе стороны оператора if.

Всегда использование предложения else с каждым оператором if является даже рекомендуемой практикой в ​​ "Code Complete".

Ответ 8

Au contraire... На мой взгляд, ДОЛЖЕН быть другим для каждого, если. Конечно, вы можете делать глупые вещи, но вы можете злоупотреблять любой конструкцией, если будете стараться достаточно усердно. Вы знаете, что "настоящий программист может писать FORTRAN на каждом языке".

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

Ответ 9

Обоснование включения оператора else (try...else) в Python в первую очередь состояло в том, чтобы только поймать те исключения, которые вы действительно хотите. Обычно, когда у вас есть блок try...except, есть код, который может вызвать исключение, а затем еще какой-то код, который должен запускаться только в том случае, если предыдущий код был успешным. Без блока else вам нужно будет поместить весь этот код в блок try:

try:
    something_that_might_raise_error()
    do_this_only_if_that_was_ok()
except ValueError:
    # whatever

Проблема в том, что если do_this_only_if_that_was_ok() вызывает a ValueError? Это может быть вызвано оператором except, если вы этого не захотели. Это цель блока else:

try:
    something_that_might_raise_error()
except ValueError:
    # whatever
else:
    do_this_only_if_that_was_ok()

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

Ответ 10

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

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

Я не считаю "еще" более опасным, чем побочные эффекты в цикле for() или неправильном управлении памятью. Все об алгоритмах. Если ваши автоматы полны по своим масштабам и возможностям, и все они конкретны и понятны, то нет никакой опасности. Опасность - это неправильное использование логики выражения людей, не понимающих влияния широкомасштабной логики. Компьютеры глупы, они делают то, что им говорит их оператор (теоретически)

Я считаю, что try и catch опасен, потому что он может отрицать обработку неизвестного количества кода. Разветвление над рейзом может содержать ошибку, выделенную самой рейкой. Это может быть неочевидным. Это похоже на превращение последовательного набора инструкций в дерево или график обработки ошибок, где каждый компонент зависит от ветвей родителя. Странно. Имейте в виду, я люблю C.

Ответ 11

Существует так называемая проблема "болтаться", которая встречается на языках семейства C следующим образом:

if (a==4)
if (b==2)
printf("here!");
else
printf("which one");

Этот невинный код можно понять двумя способами:

if (a==4)
    if (b==2)
        printf("here!");
    else
        printf("which one");

или

if (a==4)
    if (b==2)
        printf("here!");
else
    printf("which one");

Проблема в том, что "else" "свисает", можно смутить владельца else. Разумеется, компилятор не допустит этой путаницы, но это справедливо для смертных.

Благодаря Python у нас не может возникнуть проблема с болтанием еще в Python, так как мы должны написать либо

if a==4:
    if b==2:
        print "here!"
else:
    print "which one"

или

if a==4:
    if b==2:
        print "here!"
    else:
        print "which one"

Итак, человеческий глаз его поймал. И, нет, я не думаю, что "еще" вредно, это так же вредно, как "если".

Ответ 12

В примере, который может быть трудно рассуждать, он может быть написан явно, но все еще необходимо. Например.

if a < 10:       
    # condition stated explicitly   
elif a > 10 and b < 10:       
    # condition confusing but at least explicit   
else:       
    # Exactly what is true here?       
    # Can be hard to reason out what condition is true

Можно записать

if a < 10:       
    # condition stated explicitly   
elif a > 10 and b < 10:       
    # condition confusing but at least explicit   
elif a > 10 and b >=10:
    # else condition
else:   
    # Handle edge case with error?

Ответ 13

Я думаю, что точка относительно try...except...else заключается в том, что ее легко использовать для создания несогласованного состояния, а не для исправления. Это не значит, что его следует избегать любой ценой, но он может быть контрпродуктивным.

Рассмотрим:

try:
    file = open('somefile','r')
except IOError:
    logger.error("File not found!")
else:
    # Some file operations
    file.close()
# Some code that no longer explicitly references 'file'

Было бы неплохо сказать, что вышеупомянутый блок не позволял коду пытаться получить доступ к файлу, который не существовал, или к каталогу, для которого у пользователя нет разрешений, и сказать, что все инкапсулировано, потому что оно находится внутри a try...except...else. Но на самом деле много кода в приведенной выше форме действительно должно выглядеть так:

try:
    file = open('somefile','r')
except IOError:
    logger.error("File not found!")
    return False
# Some file operations
file.close()
# Some code that no longer explicitly references 'file'

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

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