Я понимаю, как работает эта конструкция:
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
Но я не понимаю, почему else
здесь используется в качестве ключевого слова, поскольку оно предполагает, что рассматриваемый код запускается только в том случае, если for
блок не завершен, что противоположно тому, что он делает! Как бы я ни думал об этом, мой мозг не может плавно переходить от for
утверждения к else
блоку. Для меня, continue
или continuewith
было бы больше смысла (и я пытаюсь научиться читать его как таковой).
Мне интересно, как Python-кодеры читают эту конструкцию в своей голове (или вслух, если хотите). Возможно, я упускаю что-то, что сделало бы такие блоки кода более легко расшифруемыми?
python
if-statement
for-loop
for-else
Кент Бугаарт
источник
источник
break
он часто используется в циклах «Я нашел это» , вы можете перевести его на «если не найдено» , что недалеко от того, чтоelse
читаетсяfor ... else foo()
и просто ставитьfoo()
после цикла for?» И ответ в том, что они ведут себя по-разному, только если цикл содержитbreak
(как подробно описано ниже).Ответы:
Это странная конструкция даже для опытных программистов Python. При использовании в сочетании с циклами for это в основном означает «найти какой-либо элемент в итерируемом элементе, в противном случае, если ничего не найдено, do ...». Как в:
Но всякий раз, когда вы видите эту конструкцию, лучшей альтернативой является инкапсуляция поиска в функции:
Или используйте понимание списка:
Он семантически не эквивалентен двум другим версиям, но работает достаточно хорошо в не критичном к производительности коде, где не имеет значения, перебираете ли вы весь список или нет. Другие могут не согласиться, но я бы лично не использовал блоки for-else или while-else в производственном коде.
Смотрите также [Python-ideas] Краткое содержание для ... еще потоков
источник
for
примерах цикла, и хотите использовать выражение выражения / списка генератора, то вы хотитеnext((o for o in objects if o.key == search_key), None)
или обернуть его вtry
/except
и не использовать значение по умолчанию вместоif
/else
.for/else
конструкцию.else
получил паруfor
и я понятия не имел, что это законно.break
оператор не является явным запуском, как в этом примере. Из документов выше: «Вelse
предложении есть еще одна проблема: еслиbreak
в цикле его нет,else
предложение функционально избыточно». напр.for x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
Обычная конструкция - запускать цикл до тех пор, пока что-то не будет найдено, а затем выйти из цикла. Проблема в том, что, если я выйду из цикла или завершу цикл, мне нужно определить, какой случай произошел. Один из способов - создать флаг или переменную хранилища, которая позволит мне выполнить второй тест, чтобы увидеть, как завершился цикл.
Например, предположим, что мне нужно искать в списке и обрабатывать каждый элемент, пока не будет найден элемент флага, а затем прекратить обработку. Если элемент флажка отсутствует, необходимо создать исключение.
Используя конструкцию Python
for
... уelse
вас естьСравните это с методом, который не использует этот синтаксический сахар:
В первом случае
raise
он тесно связан с циклом for, с которым работает. Во втором случае привязка не так сильна, и во время обслуживания могут возникать ошибки.источник
Python: the good parts
книгу.process(i)
происходит для каждого элементаmylist
строго раньшеtheflag
, а не сtheflag
самим собой? Это то, что было задумано?process
будет выполняться для каждого,i
который существует в списке доtheflag
его достижения, он не будет выполняться для элементов в списке послеtheflag
, и он не будет выполняться дляtheflag
.Есть отличная презентация Раймонда Хеттингера под названием « Преобразование кода в красивый идиоматический Python» , в которой он кратко рассказывает об истории
for ... else
конструкции. Соответствующий раздел «Различение нескольких точек выхода в циклах» начинается с 15:50 и продолжается около трех минут. Вот основные моменты:for ... else
Конструкция была разработана Дональдом Кнутом в качестве замены для некоторыхGOTO
случаев применения;else
ключевых слов имеют смысл , потому что «это то , что раньше Кнут, и люди знали, в то время, все [for
заявления] были заделаныif
иGOTO
внизу, и они ожидалиelse
;»Итак, если вопрос таков: «Почему они не меняют это ключевое слово?» тогда Cat Plus Plus, вероятно, дал самый точный ответ - на данный момент, он был бы слишком разрушительным для существующего кода, чтобы быть практичным. Но если вопрос, который вы действительно задаете, заключается в том, почему
else
его вообще использовали повторно, ну, по-видимому, в то время это казалось хорошей идеей.Лично мне нравится компромисс в комментариях
# no break
в строке, гдеelse
, на первый взгляд, можно ошибочно принять принадлежность внутри цикла. Это достаточно ясно и кратко. Эта опция получает краткое упоминание в резюме, которое Бьорн связал в конце своего ответа:* Бонусная цитата из той части видео: «Точно так же, как если бы мы назвали лямбда- функцию, никто бы не спросил:« Что делает лямбда? »
источник
Потому что они не хотели вводить новое ключевое слово в язык. Каждый из них ворует идентификатор и вызывает проблемы обратной совместимости, поэтому обычно это последнее средство.
источник
finally
, было бы лучшим выбором в этом случае. Не было ли еще ключевого слова finally во время введения этой конструкции?finally
не намного лучше, потому что он подразумевает, что блок всегда будет выполняться после цикла, и это не так (потому что это было бы избыточно, если просто поместить код для запуска после цикла).finally
потому что условие else выполняется также, когдаcontinue
используется в цикле for - это возможно много раз, а не только в конце.else
выполнение условия @pepr не влияютcontinue
( документы и тестовый код )else
Выполняется только тогда , когдаcontinue
был один для последней итерации.Чтобы сделать это простым, вы можете думать об этом так;
break
команду вfor
цикле,else
часть не будет вызвана.break
команду вfor
цикле,else
будет вызвана часть.Другими словами, если для цикла итерация не «нарушена»
break
,else
будет вызвана часть.источник
else
Блок также не будет выполнен , если тело цикла вызывает исключение.Самый простой способ, которым я нашел «получить» то, что сделал for / else, и, что более важно, когда его использовать, - это сконцентрироваться на том, куда переходит оператор break. Конструкция For / else представляет собой один блок. Перерыв выпрыгивает из блока и, таким образом, перепрыгивает через условие else. Если бы содержимое предложения else просто следовало за предложением for, оно никогда бы не перепрыгнуло, и поэтому эквивалентную логику нужно было бы предоставить, поместив его в if. Это было сказано ранее, но не совсем в этих словах, так что это может помочь кому-то еще. Попробуйте запустить следующий фрагмент кода. Я искренне поддерживаю комментарий «без перерыва» для ясности.
источник
for:
/else:
, на самом деле это не дает оправдания ключевому словуelse
. Учитывая приведенную здесь структуру,then:
кажется, что это было бы гораздо более естественным. (Там являются причиныelse
быть выбраны, приведенные в других ответах - они просто не предусмотрены здесь.)Я думаю , что документация имеет большое объяснение еще , по- прежнему
Источник: Python 2 документы: Учебник по потоку управления
источник
Я прочитал это что-то вроде:
Если все еще на условиях для запуска цикла, делать что- то , а что-то делать еще.
источник
for:
/else:
делает его звучащим так, как будто оноelse:
всегда запускается после цикла, что не так.Поскольку техническая часть получила довольно много ответов, мой комментарий просто связан с путаницей , в которой возникает это переработанное ключевое слово.
Будучи Python очень красноречивым языком программирования, злоупотребление ключевым словом является более печально известным.
else
Ключевое слово прекрасно описывает часть потока дерева решений, «если вы не можете сделать это, (еще) сделать это». Это подразумевается на нашем родном языке.Вместо этого, используя это ключевое слово с
while
иfor
заявления создает путаницу. Причина, по которой наша карьера программиста научила нас тому, чтоelse
утверждение находится в дереве решений; его логическая область - оболочка, которая условно возвращает путь, по которому нужно следовать. Между тем, циклические операторы имеют явную явную цель чего-то достичь. Цель достигается после непрерывных итераций процесса.if / else
указать путь для подражания . Петли следуют по пути, пока «цель» не будет достигнута .Проблема в том, что
else
это слово четко определяет последний параметр условия. В семантику этого слова оба разделяют на Python и человеческого языка. Но другое слово в человеческом языке никогда не используется для обозначения действий, которые кто-то или что-либо предпримет после того, как что-то будет выполнено. Он будет использоваться, если в процессе его завершения возникнет проблема (больше похожая на оператор прерывания ).В конце ключевое слово останется в Python. Понятно, что это была ошибка, понятнее, когда каждый программист пытается придумать историю, чтобы понять ее использование как какое-то мнемоническое устройство. Я бы любил, если бы они выбрали вместо этого ключевого слова
then
. Я считаю, что это ключевое слово идеально вписывается в этот итеративный поток, результат после цикла.Это напоминает ту ситуацию, которая возникает у какого-то ребенка после выполнения каждого шага при сборке игрушки: А ТО какой папа?
источник
Я читаю это как «Когда
iterable
полностью исчерпан, и выполнение собирается перейти к следующему оператору после завершенияfor
, будет выполнено предложение else». Таким образом, когда итерация нарушенаbreak
, это не будет выполнено.источник
Я согласен, это больше похоже на 'elif not [условие (и), повышающее разрыв]'.
Я знаю, что это старая ветка, но сейчас я изучаю тот же вопрос, и я не уверен, что кто-то получил ответ на этот вопрос так, как я его понимаю.
Для меня есть три способа «чтения» операторов
else
inFor... else
илиWhile... else
, все из которых эквивалентны:else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
else not (condition raising break)
(предположительно, есть такое условие, иначе у вас не будет петли)Таким образом, по сути, «else» в цикле - это действительно «elif ...», где «...» - это (1) без перерыва, что эквивалентно (2) NOT [условие (я), поднимающее разрыв].
Я думаю, что ключ в том, что
else
без «перерыва» бессмысленно, так чтоfor...else
включает в себя:Итак, основными элементами
for...else
цикла являются следующие, и вы бы прочитали их на простом английском языке как:Как говорили другие авторы, разрыв обычно возникает, когда вы можете найти то, что ищет ваш цикл, поэтому
else:
становится «что делать, если целевой элемент не найден».пример
Вы также можете использовать обработку исключений, разрывы и циклы for все вместе.
Результат
пример
Простой пример с разрывом удара.
Результат
пример
Простой пример, где нет перерыва, нет условия, поднимающего перерыв, и нет ошибки.
Результат
источник
else
Ключевое слово может сбивать с толку здесь, и , как многие люди отмечали, что - то вродеnobreak
,notbreak
более уместно.Для того , чтобы понять
for ... else ...
логически, сравнить его сtry...except...else
, а неif...else...
большинство питона программистов знакомы со следующим кодом:Точно так же думайте
break
как особый видException
:Разница
python
подразумеваетсяexcept break
и вы не можете ее выписать, поэтому она становится:Да, я знаю, что это сравнение может быть трудным и утомительным, но оно проясняет путаницу.
источник
Коды в
else
блоке операторов будут выполняться, когдаfor
цикл не был прерван.Из документов: ломайте и продолжайте утверждения, а также пункты о циклах
источник
Вот способ подумать об этом, которого я не видел ни у кого из упомянутых выше:
Во-первых, помните, что циклы for - это просто синтаксический сахар вокруг циклов while. Например, цикл
можно переписать (примерно) как
Во-вторых, помните, что циклы while - это просто повторяющиеся блоки if! Вы всегда можете прочитать цикл while как «если это условие истинно, выполнить тело, а затем вернуться и проверить снова».
Так что, хотя / else имеет смысл: это та же структура, что и if / else, с добавленной функциональностью зацикливания до тех пор, пока условие не станет ложным, вместо простой проверки условия один раз.
И тогда for / else также имеет смысл: поскольку все циклы for являются просто синтаксическим сахаром поверх циклов while, вам просто нужно выяснить, каково неявное условное выражение базового цикла while, а затем else соответствует тому, когда состояние становится ложным.
источник
Великолепные ответы:
Моя заметка здесь взята из того, что однажды сказал Дональд Кнут (извините, не могу найти ссылку), что существует конструкция, в которой while-else неотличима от if-else, а именно (в Python):
имеет такой же поток (исключая низкие разности уровней) как:
Дело в том, что if-else можно рассматривать как синтаксический сахар для while-else, который неявно присутствует
break
в конце своегоif
блока. Противоположный вывод, чтоwhile
цикл является расширениемif
, является более распространенным (это просто повторная / циклическая условная проверка), потому чтоif
часто учат раньшеwhile
. Однако это не так, потому что это будет означать, чтоelse
блок while-else будет выполняться каждый раз когда условие ложно.Чтобы облегчить ваше понимание, подумайте об этом так:
Еще одна заметка:
источник
Вы можете думать об этом как,
else
как в остальной части материала, или о других вещах, которые не были сделаны в цикле.источник
«остальное» здесь безумно просто, просто значит
1, «если
for clause
завершено»Имеет смысл написать такие длинные операторы, как «предложение завершено», поэтому они вводят «еще».
else
вот если бы по своей природе.2, однако, как насчет
for clause is not run at all
Так что это полностью утверждение логической комбинации:
или скажем так:
или так:
источник
Вот еще один идиоматический вариант использования помимо поиска. Допустим, вы хотели дождаться выполнения условия, например, открытия порта на удаленном сервере, а также некоторого времени ожидания. Тогда вы можете использовать такую
while...else
конструкцию:источник
Я просто пытался понять это снова сам. Я обнаружил, что следующее помогает!
• Думайте о том,
else
что он связан сif
внутренним циклом (а не сfor
) - если условие выполнено, прервите цикл, иначе сделайте это - за исключением того, что онelse
связан с несколькимиif
s!• Если никакие
if
s не были удовлетворены вообще, тогда сделайтеelse
.• Множество
if
s также может рассматриваться какif
-elif
s!источник
Я рассматриваю структуру как для (если) A else B, так и для (if) -sese является специальным if-else , примерно . Это может помочь понять другое .
A и B выполняются не более одного раза, что аналогично структуре if-else.
for (if) может рассматриваться как особый if, который выполняет цикл для выполнения условия if. Как только условие if выполнено, A и перерыв ; Остальное , Б.
источник
Python использует циклы else after for и while, так что если к циклу ничего не применяется, происходит что-то еще. Например:
Вывод будет «Привет» снова и снова (если я прав).
источник