Как я могу понять предложение "else" циклов Python?
многие программисты Python, вероятно, не знают, что синтаксис while
петли и for
петли включает в себя дополнительный else:
статья:
for val in iterable:
do_something(val)
else:
clean_up()
тело else
предложение является хорошим местом для определенных видов действий очистки и выполняется при нормальном завершении цикла: т. е., выход из цикла с return
или break
переход else
предложение; выход после continue
выполняет его. Я знаю это только потому, что я просто посмотрел (пока опять же), потому что я никогда не могу вспомнить , когда the else
пункт выполняется.
всегда? О "провале" цикла, как следует из названия? На обычном увольнении? Даже если цикл выходит с return
? Я никогда не могу быть полностью уверен, не посмотрев его.
я виню свою сохраняющуюся неопределенность в выборе ключевого слова: я нахожу else
невероятно unmnemonic для этой семантики. Мой вопрос не "почему это ключевое слово используется для этой цели" (который я вероятно, проголосовали бы за закрытие, хотя только после прочтения ответов и комментариев), но как я могу думать о else
ключевое слово, чтобы его семантика имела смысл, и поэтому я могу его запомнить?
я уверен, что об этом было много дискуссий, и я могу себе представить, что выбор был сделан для согласованности с try
заявление else:
предложение (которое я также должен посмотреть), и с целью не добавлять в список зарезервированных Python слова. Возможно, причины выбора else
прояснит свою функцию и сделает ее более запоминающейся, но я после подключения имени к функции, а не после исторического объяснения как такового.
ответы этот вопрос, который мой вопрос был кратко закрыт как дубликат, содержит много интересной предыстории. Мой вопрос имеет другой фокус (как подключить конкретную семантику else
С выбором ключевого слова), но я чувствую, что должна быть ссылка на этот вопрос где-то.
14 ответов
(это вдохновлено ответом @Mark Tolonen.)
An if
оператор запускает свой else
предложение, если его условие равно false.
Тождественно, a while
loop запускает предложение else, если его условие равно false.
это правило соответствует описанному вами поведению:
- при нормальном выполнении цикл while многократно выполняется, пока условие не будет равно false, и поэтому при естественном выходе из цикла выполняется else пункт.
- при выполнении
break
оператор, вы выходите из цикла без оценки условия, поэтому условие не может оцениваться как false, и вы никогда не запускаете предложение else. - при выполнении
continue
оператор, вы снова оцениваете условие и делаете именно то, что обычно делали бы в начале итерации цикла. Итак, если условие истинно, вы продолжаете цикл, но если оно ложно, вы запускаете предложение else. - другие методы выход из цикла, например
return
, не оценивайте условие и поэтому не запускайте предложение else.
for
петли ведут себя одинаково. Просто учитывайте состояние как true, если итератор имеет больше элементов, или false в противном случае.
лучше думать об этом так:else
блок всегда будет выполнено, если все пойдет право в предыдущем for
блок такой, что он достигает истощения.
право в этом контексте означает нет exception
, нет break
, нет return
. Любое заявление, которое захватывает контроль из for
вызывает else
блок, который нужно обойти.
общий случай использования при поиске элемента в iterable
, для которого поиск либо отменяется, когда элемент найден, либо "not found"
флаг поднят / напечатан через следующее else
блок:
for items in basket:
if isinstance(item, Egg):
break
else:
print("No eggs in basket")
A continue
не захватывает управление из for
, поэтому управление перейдет к else
после for
исчерпан.
когда if
выполнить else
? Когда условие ложно. Это точно то же самое для while
/else
. Так что вы можете думать о while
/else
Как только if
который продолжает работать в своем истинном состоянии, пока не оценит false. А break
ничего не меняет. Это просто скачки содержащего цикла без оценки. The else
выполняется только если оценка the if
/while
условие ложно.
на for
is аналогично, за исключением того, что его ложное условие исчерпывает его итератор.
continue
и break
не выполнять else
. Это не их функция. The break
выходит из содержащего цикла. The continue
возвращается в верхнюю часть содержащего цикла, где оценивается условие цикла. Это акт оценки if
/while
false (или for
больше нет элементов), который выполняет else
и нет другого пути.
вот что это по существу означает:
for/while ...:
if ...:
break
if there was a break:
pass
else:
...
это более приятный способ написания этой общей картины:
found = False
for/while ...:
if ...:
found = True
break
if not found:
...
на else
предложение не будет выполнено, если есть return
, потому что return
оставляет функцию, как она предназначена. Единственное исключение из того, о чем вы можете думать, - это finally
, чья цель состоит в том, чтобы быть уверенным, что он всегда выполняется.
continue
не имеет ничего общего с этим вопросом. Оно вызывает ток итерация цикла до конца, которая может привести к завершению всего цикла, и, очевидно, в этом случае цикл не был завершен break
.
try/else
аналогично:
try:
...
except:
...
if there was an exception:
pass
else:
...
если вы думаете о своих циклах как о структуре, подобной этой (несколько псевдо-код):
loop:
if condition then
... //execute body
goto loop
else
...
это может иметь немного больше смысла. Цикл по существу просто if
оператор, который повторяется до тех пор, пока условие не false
. И это важный момент. Цикл проверяет свое состояние и видит, что это false
, таким образом, выполняет else
(так же, как нормальный if/else
), а затем цикл выполняется.
отметим, что else
только get выполняется при проверке условия. Это означает, что если вы выходите из тела цикла в середине исполнения, например,return
или break
, так как условие не проверяется,else
дело не будет выполнено.
A continue
С другой стороны, останавливает текущее выполнение, а затем возвращается, чтобы снова проверить состояние цикла, поэтому else
может быть достигнуто в этом случае.
мой момент с петлей else
предложение было, когда я смотрел разговор Компания Raymond Hettinger, который рассказал историю о том, как, по его мнению, она должна была называться nobreak
. Взгляните на следующий код, как вы думаете он будет делать?
for i in range(10):
if test(i):
break
# ... work with i
nobreak:
print('Loop completed')
как вы думаете, что он делает? Ну, та часть, которая говорит nobreak
будет выполняться только если break
заявление не попало в петлю.
обычно я склонен думать о структуре цикла, как это:
for item in my_sequence:
if logic(item):
do_something(item)
break
чтобы быть похожим на переменное число if/elif
отчетность:
if logic(my_seq[0]):
do_something(my_seq[0])
elif logic(my_seq[1]):
do_something(my_seq[1])
elif logic(my_seq[2]):
do_something(my_seq[2])
....
elif logic(my_seq[-1]):
do_something(my_seq[-1])
в этом случае else
оператор на цикле for работает точно так же, как else
заявление по цепочке elif
s, он выполняется только в том случае, если ни одно из условий перед его оценкой не равно True. (или прервать выполнение с помощью return
или исключение) если мой цикл не соответствует этой спецификации, как правило, я выбираю отказаться от используя for: else
по той же причине, по которой вы опубликовали этот вопрос: он не интуитивно понятен.
другие уже объяснили механику while/for...else
и Python 3 ссылка на язык есть авторитетное определение (см. пока и на), но вот моя личная мнемоника, FWIW. Я думаю, ключом для меня было разбить это на две части: одна для понимания значения else
по отношению к условному циклу и один для понимания управления циклом.
мне проще начать с понимание while...else
:
while
у вас есть больше деталей, делать вещи,else
Если вы закончите, сделайте это
на for...else
мнемоника в основном то же самое:
for
каждый пункт, делать вещи, ноelse
Если вы закончите, сделайте это
в обоих случаях else
часть достигается только после того, как больше нет элементов для обработки, и последний элемент был обработан в обычным образом (т. е. без break
или return
). А continue
просто возвращается и видит, есть ли еще какие-либо элементы. Моя мнемоника для этих правил относится к обоим while
и for
:
, когда
break
ing илиreturn
Инг, там ничегоelse
делать
и когда я говорюcontinue
, это "цикл назад, чтобы начать" для вас
- С "loop back to start" означает, очевидно, начало цикла, где мы проверяем, есть ли есть ли еще элементы в iterable, так как else
обеспокоен, continue
действительно не играет никакой роли.
как я это вижу,else:
срабатывает, когда вы проходите мимо конца цикла.
если вы break
или return
или raise
вы не проходите мимо конца цикла, вы останавливаетесь immeadiately, и, таким образом,else:
блок не будет работать. Если ты ... --5--> вы все еще повторяете конец цикла, так как continue просто переходит к следующей итерации. Это не останавливает петлю.
думать else
предложение как часть конструкции цикла;break
полностью выходит из конструкции цикла и, таким образом, пропускает else
предложения.
но на самом деле, мое ментальное отображение просто в том, что это "структурированная" версия шаблона C/C++ pattern:
for (...) {
...
if (test) { goto done; }
...
}
...
done:
...
поэтому, когда я сталкиваюсь с for...else
или писать его самому, а не понимать его.напрямую, Я мысленно перевожу его в вышеупомянутое понимание шаблона, а затем работаю какие части синтаксиса python сопоставляются с какими частями шаблона.
(я ставлю "структурированный" в кавычки, потому что разница не в том, структурирован ли код или неструктурирован, а просто есть ли ключевые слова и грамматика, посвященные конкретной структуре)
как я думаю об этом, ключ должен учитывать значение continue
, а не else
.
другие ключевые слова, которые вы упоминаете вырваться из цикла (выход ненормально) в то время как continue
нет, он просто пропускает оставшуюся часть блока кода внутри цикла. Тот факт, что он может предшествовать завершению цикла, является случайным: завершение фактически выполняется обычным способом путем оценки условного выражения цикла.
тогда вам просто нужно помнить, что the else
предложение выполняется после завершения обычного цикла.
если вы пытаетесь выполнить сопряжение else
с for
в вашем уме, это может сбить с толку. Я не думаю, что ключевое слово else
был отличным выбором для этого синтаксиса, но если вы соедините else
с break
, вы можете видеть, что это действительно имеет смысл.
позвольте мне продемонстрировать это на человеческом языке.
for
каждый человек в группе подозреваемыхif
любой преступникbreak
следствие.else
отчет неудача.
else
едва ли полезно, если бы не break
на for
цикл в любом случае.
# tested in Python 3.6.4
def buy_fruit(fruits):
'''I translate the 'else' below into 'if no break' from for loop '''
for fruit in fruits:
if 'rotten' in fruit:
print(f'do not want to buy {fruit}')
break
else: #if no break
print(f'ready to buy {fruits}')
if __name__ == '__main__':
a_bag_of_apples = ['golden delicious', 'honeycrisp', 'rotten mcintosh']
b_bag_of_apples = ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
buy_fruit(a_bag_of_apples)
buy_fruit(b_bag_of_apples)
'''
do not want to buy rotten mcintosh
ready to buy ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
'''