Многие программисты Python, вероятно, не знают, что синтаксис while
циклов и for
циклов включает необязательное else:
предложение:
for val in iterable:
do_something(val)
else:
clean_up()
Тело else
предложения является хорошим местом для определенных видов действий по очистке и выполняется при обычном завершении цикла: то есть, выход из цикла с предложением return
или break
пропуск else
предложения; выход после того, как continue
выполняет его. Я знаю это только потому, что только что посмотрел (еще раз), потому что не могу вспомнить, когда было выполнено else
предложение.
Всегда? На «провал» цикла, как следует из названия? На регулярное прекращение? Даже если цикл завершен с return
? Я никогда не могу быть полностью уверен, не глядя на это.
Я виню свою сохраняющуюся неопределенность в выборе ключевого слова: я нахожу else
невероятно немонемным для этой семантики. Мой вопрос не в том, «почему это ключевое слово используется для этой цели» (за который я бы, вероятно, проголосовал бы, хотя бы только после прочтения ответов и комментариев), а как я могу подумать о else
ключевом слове, чтобы его семантика имела смысл, и я может поэтому помнить это?
Я уверен, что было довольно много обсуждений по этому поводу, и я могу себе представить, что выбор был сделан для соответствия с предложением try
заявления else:
(которое я также должен посмотреть), и с целью не добавлять в список Зарезервированные слова Python. Возможно, причины выбора else
прояснят его функцию и сделают его более запоминающимся, но я после соединения имени с функцией, а не после исторического объяснения как такового.
Ответы на этот вопрос , который мой вопрос был кратко закрыт как дубликат, содержат много интересных предысторий. Мой вопрос имеет другую направленность (как связать определенную семантику else
с выбором ключевого слова), но я чувствую, что где-то должна быть ссылка на этот вопрос.
источник
else
основном означает «если условие продолжения не выполнено». В традиционном цикле for условием продолжения обычно являетсяi < 42
: в этом случае вы можете просмотреть эту часть какif i < 42; execute the loop body; else; do that other thing
break
. Канонический вариант использования - это когда цикл ищет что-то и прерывается, когда он это находит.else
Выполняется только тогда , когда ничего не найдено.Ответы:
(Это вдохновлено ответом @Mark Tolonen.)
if
Оператор запускает егоelse
предложение , если его состояние оценивается как ложное. Идентично,while
цикл запускает предложение else, если его условие оценивается как ложное.Это правило соответствует описанному вами поведению:
break
оператор, вы выходите из цикла без оценки условия, поэтому условие не может быть оценено как ложное, и вы никогда не выполняете предложение else.continue
оператор, вы снова оцениваете условие и делаете то, что обычно делаете в начале итерации цикла. Итак, если условие истинно, вы продолжаете цикл, но если оно ложно, вы запускаете предложение else.return
, не оценивают условие и поэтому не запускают предложение else.for
петли ведут себя одинаково. Просто считайте условие истинным, если итератор имеет больше элементов, или ложным в противном случае.источник
elif
утверждений. Есть ответ, который делает, и у него есть одно чистое голосование.break
, и в этом случаеelse
условие не будет выполняться, но условие будет False Точно так же сfor
циклами это можетbreak
на последнем элементе.Лучше думать об этом так:
else
блок будет всегда выполняться , если все идет прямо в предыдущемfor
блоке таким образом, что она достигает истощения.Право в этом контексте будет означать нет
exception
, нетbreak
, нетreturn
. Любое утверждение, от которого перехватывает управлениеfor
, приведет кelse
обходу блока.Обычный вариант использования обнаруживается при поиске элемента в
iterable
, для которого поиск либо отменяется, когда элемент найден, либо"not found"
флаг поднимается / печатается с помощью следующегоelse
блока:A
continue
не перехватывает управление уfor
, поэтому управление переходит к тому,else
когдаfor
истощен.источник
else
предложение будет выполнено, когда дела пойдут не так , не так ли? Я уже запутался снова ...else
]», посколькуelse
он запускается, когда ни одно из условий в цикле for не принимает значение True, как я демонстрирую в своем ответеFalse
. Таким образом, вопрос о том, какfor
это сломано, зависит от варианта использования.else
в python). Вы предоставляете хорошую интуитивную сводку о томelse
, что делает @Moses, но не о том, как мы могли бы связать это поведение с «else». Если бы использовалось другое ключевое слово (например,nobreak
как упомянуто в этом ответе на связанный вопрос), это было бы легче понять.if
/while
оценивается как ложное илиfor
нет элементов.break
существует содержащий цикл (послеelse
).continue
возвращается и снова оценивает состояние цикла.Когда
if
выполнитьelse
? Когда его условие ложно. Это точно так же дляwhile
/else
. Таким образом, вы можете думать оwhile
/else
как о просто,if
который продолжает работать в своем истинном состоянии, пока не оценит ложное. Аbreak
это не меняет. Он просто выпрыгивает из содержащего цикла без оценки.else
Выполняется только при оценке вif
/while
условие ложно.for
Аналогично, за исключением его ложное условие исчерпав итератор.continue
иbreak
не казнитьelse
. Это не их функция. Выходbreak
из содержащего цикла.continue
Восходит к верхней части , содержащей петли, где вычисляется условие цикла. Это акт оценкиif
/while
ложь (илиfor
не имеет больше элементов), который выполняется,else
и никак иначе.источник
else
предложение выполняется, если цикл завершается сcontinue
(или обычно), но нет, если мы выйдем сbreak
. Именно из-за этих тонкостей я пытаюсь понять, чтоelse
ловит, а что нет.Вот что это по сути означает:
Это более хороший способ написания этого общего шаблона:
Предложение
else
не будет выполнено, если есть,return
потому чтоreturn
оставляет функцию, как это и предполагалось. Единственное исключение из того, о чем вы, возможно, думаете, это тоfinally
, чья цель - быть уверенным, что оно всегда выполняется.continue
не имеет ничего общего с этим вопросом. Это приводит к тому, что текущая итерация цикла заканчивается, что может привести к завершению всего цикла, и, очевидно, в этом случае цикл не был завершен с помощью abreak
.try/else
похож:источник
Если вы думаете о своих циклах как о структуре, похожей на эту (несколько псевдокод):
это может иметь немного больше смысла. Цикл - это, по сути, просто
if
оператор, который повторяется до тех пор, пока не выполнится условиеfalse
. И это важный момент. Цикл проверяет свое состояние и видит, что онfalse
, таким образом, выполняетelse
(как обычноif/else
), а затем цикл завершается.Так что обратите внимание, что
else
единственное получение выполняется при проверке условия . Это означает, что если вы выйдете из тела цикла в середине выполнения, например, с помощью areturn
или abreak
, поскольку условие не проверяется снова,else
случай не будет выполнен.A,
continue
с другой стороны, останавливает текущее выполнение, а затем переходит назад, чтобы снова проверить состояние цикла, поэтомуelse
в этом сценарии можно достичь этого.источник
end
ярлык и просто поместите егоgoto loop
внутрьif
корпуса. Может быть, даже превзойти, поместив надписьif
на той же строке, что и метка, и это внезапно очень похоже на оригинал.Мой момент с
else
пунктом цикла был, когда я смотрел лекцию Рэймонда Хеттингера , который рассказал историю о том, как, по его мнению, это должно было быть названоnobreak
. Посмотрите на следующий код, как вы думаете, что он будет делать?Что бы вы предположили, что это делает? Ну, часть, которая говорит,
nobreak
будет выполнена, только еслиbreak
оператор не попадет в цикл.источник
Обычно я склонен думать о такой структуре цикла:
Чтобы быть очень похожим на переменное количество
if/elif
утверждений:В этом случае
else
оператор в цикле for работает точно так же, какelse
оператор в цепочкеelif
s, он выполняется только в том случае, если ни одно из условий перед тем, как он оценивается как True. (или прервать выполнение с помощьюreturn
или исключение) Если мой цикл не соответствует этой спецификации, обычно я выбираю отказаться от использованияfor: else
по той причине, по которой вы задали этот вопрос: он не интуитивен.источник
Другие уже объяснили механику
while/for...else
, а также справочник по языку Python 3 имеет официальное определение (см в то время как и для ), но вот мой личный мнемонические, FWIW. Я думаю, что ключом для меня было разделить это на две части: одну для понимания смыслаelse
относительно условного цикла, а другую для понимания управления циклом.Я считаю, что проще всего начать с понимания
while...else
:for...else
Мнемонические в основном то же самое:В обоих случаях эта
else
часть достигается только в том случае, если больше нет элементов для обработки, а последний элемент обработан обычным образом (т. Е. Нетbreak
илиreturn
). Аcontinue
просто возвращается и видит, есть ли еще предметы. Моя Мнемоника для этих правил относится какwhile
иfor
:- с «loop back to start», означающим, очевидно, начало цикла, где мы проверяем, есть ли еще какие-либо элементы в итерируемом, поскольку
else
этоcontinue
действительно не играет никакой роли.источник
else
Может также использоваться , чтобы сделать что - то , когда вы просто закончили со всеми пунктами. Примеры включают написание записи в журнале, обновление пользовательского интерфейса или сигнал о каком-то другом процессе, который вы сделали. Ничего действительно. Кроме того, некоторые фрагменты кода имеют «успешный» конец дела сbreak
внутренним циклом, иelse
он используется для обработки «ошибки», когда вы не нашли подходящего элемента во время итерации (возможно, именно об этом вы и думали из?).else
блок цикла или отслеживать результат, используя другие средства. Я в основном согласен, я просто говорю, что не знаю, как люди используют эту функцию, и поэтому я бы хотел избежать предположений о том, является лиelse
сценарий « обрабатывает успешное дело» или «else
обрабатывает неудачное дело» более распространенным. Но у вас есть хорошая точка зрения, поэтому комментируйте, проголосовали!В управляемой тестами разработке (TDD) при использовании парадигмы Transformation Priority Premise вы рассматриваете циклы как обобщение условных операторов.
Этот подход хорошо сочетается с этим синтаксисом, если вы рассматриваете только простые
if/else
(нетelif
) операторы:обобщает до:
приятно.
На других языках TDD переходит от одного случая к случаям с коллекциями и требует большего рефакторинга.
Вот пример из блога 8thlight :
В связанной статье в блоге 8thlight рассматривается ката Word Wrap: добавление разрывов строк к строкам (
s
переменная в фрагментах ниже), чтобы они соответствовали заданной ширине (length
переменная в фрагментах ниже). В какой-то момент реализация выглядит следующим образом (Java):и следующий тест, который в настоящее время не проходит:
Итак, у нас есть код, который работает условно: при выполнении определенного условия добавляется разрыв строки. Мы хотим улучшить код для обработки нескольких разрывов строк. Представленное в статье решение предлагает применить преобразование (if-> while) , однако автор комментирует следующее:
что заставляет делать больше изменений в коде в контексте одного неудачного теста:
В TDD мы хотим написать как можно меньше кода для прохождения тестов. Благодаря синтаксису Python возможно следующее преобразование:
из:
чтобы:
источник
Как я вижу,
else:
срабатывает, когда вы перебираете конец цикла.Если вы
break
илиreturn
илиraise
вы не итерация в конце прошлого цикла, вы перестаете immeadiately, и , таким образом,else:
блок не будет работать. Если выcontinue
все еще итерируете после окончания цикла, поскольку продолжить просто пропускает к следующей итерации. Это не останавливает цикл.источник
goto
вершина была успешной.) Но это более короткая версия ответа сДумайте о
else
предложении как о части конструкции цикла;break
полностью выходит из конструкции цикла и пропускаетelse
предложение.Но на самом деле мое умственное отображение состоит в том, что это «структурированная» версия шаблона C / C ++:
Поэтому, когда я сталкиваюсь
for...else
или пишу это сам, вместо того, чтобы понимать это непосредственно , я мысленно преобразую это в приведенное выше понимание шаблона, а затем выясняю, какие части синтаксического синтаксиса python сопоставляются с какими частями шаблона.(Я поместил «структурированный» в страшные кавычки, потому что разница не в том, является ли код структурированным или неструктурированным, а просто в том, есть ли ключевые слова и грамматика, выделенные для конкретной структуры)
источник
else
? Если вы имели в виду, чтоdone:
лейбл стоит в качестве прокси-сервера илиelse:
, я полагаю, у вас это точно в обратном направлении.done:
этикетке. Общее соответствие, пожалуй, лучше всего сказать так: Python имеет конструкциюelse
-on-loop, так что вы можете выразить этот шаблон потока управления безgoto
.else
избегает.Если вы соединитесь
else
сfor
, это может сбить с толку. Я не думаю, что ключевое словоelse
было отличным выбором для этого синтаксиса, но если вы создадите паруelse
с тем,if
который содержитbreak
, вы увидите, что это действительно имеет смысл.else
вряд ли пригодится, если нет предшествующегоif
утверждения, и я считаю, что именно поэтому разработчик синтаксиса выбрал ключевое слово.Позвольте мне продемонстрировать это на человеческом языке.
источник
То, как я думаю об этом, ключ, чтобы рассмотреть значение,
continue
а неelse
.Другие ключевые слова, о которых вы упомянули, выходят из цикла (выходят ненормально), хотя
continue
этого не происходит, он просто пропускает оставшуюся часть блока кода внутри цикла. Тот факт, что он может предшествовать завершению цикла, является случайным: на самом деле завершение выполняется обычным способом путем вычисления условного выражения цикла.Тогда вам просто нужно помнить, что
else
предложение выполняется после обычного завершения цикла.источник
источник