Почему python использует «else» после циклов for и while? - PullRequest
376 голосов
/ 02 апреля 2012

Я понимаю, как работает эта конструкция:

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-кодеры читают эту конструкцию в своей голове (или вслух, если хотите). Возможно, мне не хватает чего-то, что сделало бы такие кодовые блоки более легко расшифрованными?

Ответы [ 21 ]

5 голосов
/ 06 января 2016

Я согласен, это больше похоже на 'elif not [условие (и), поднимающее разрыв]'.

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

Для меня есть три способа «прочитать» else в For... elseили While... else утверждений, все из которых эквивалентны:

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (предположительно, есть такое условие, или у вас не будет цикла)

Так что, по сути, «другое» вцикл - это действительно "elif ...", где '...' - это (1) без перерыва, что эквивалентно (2) НЕ [условию (ам), поднимающему разрыв].

Я думаю, что ключ в том, что else бессмысленно без 'перерыва', поэтому for...else включает в себя:

for:
    do stuff
    conditional break # implied by else
else not break:
    do more stuff

Итак, основные элементы цикла for...else таковы, и выбудет читать их на простом английском языке как:

for:
    do stuff
    condition:
        break
else: # read as "else not break" or "else not condition"
    do more stuff

Как говорили другие авторы, перерыв обычно возникает, когда вы можете найти то, что ищет ваш цикл, поэтому else: становится «что делать, если целевой элемент не найден».

Пример

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

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
        try:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
        except:
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
            break
else:
    print("X loop complete without error")

Результат

x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run

Пример

Простой пример с ударом перерыва.

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
        break
else: # not executed because break is hit
    print("y_loop completed without break----------\n")

Результат

y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run

Пример

Простой пример, когда нет перерыва, нет условия, вызывающего перерыв, и нет ошибок.

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
         break
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
     print("z_loop complete without break or error\n----------\n")

Результат

z: 0
z: 1
z: 2
z_loop complete without break or error
----------
4 голосов
/ 11 декабря 2018

Вот способ подумать о том, что я не видел, чтобы кто-то еще упомянул выше:

Во-первых, помните, что for-циклы - это просто синтаксический сахар вокруг while-циклов.Например, цикл

for item in sequence:
    do_something(item)

можно переписать (приблизительно) как

item = None
while sequence.hasnext():
    item = sequence.next()
    do_something(item)

Во-вторых, помните, что циклы while в основном просто повторяются, если-блоки!Вы всегда можете прочитать цикл while как «если это условие истинно, выполнить тело, затем вернуться и проверить снова».

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

И тогда for / else также имеет смысл: все циклы for являются просто синтаксическим сахаром поверх-loops, вам просто нужно выяснить, каково неявное условное выражение базового цикла while, а затем другое соответствует тому, когда это условие становится False.

4 голосов
/ 27 апреля 2017

Ключевое слово else может сбивать с толку, и, как отмечают многие, что-то вроде nobreak, notbreak более уместно.

Чтобы логически понять for ... else ..., сравнитес try...except...else, а не if...else..., большинство программистов на Python знакомы со следующим кодом:

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

Аналогично, break можно рассматривать как особый вид Exception:

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

Разница в python подразумевает except break, и вы не можете выписать это, поэтому оно становится:

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

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

4 голосов
/ 26 августа 2016

Коды в блоке операторов else будут выполняться, когда цикл for не был прерван.

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

Из документов : операторы прерывания и продолжения, а также пункты о циклах

Операторы цикла могут иметь предложение else; он выполняется, когда цикл завершается из-за исчерпания списка (с помощью for) или когда условие становится ложным (с помощью while), но не тогда, когда цикл завершается оператором break. Это иллюстрируется следующим циклом, который ищет простые числа:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(Да, это правильный код. Посмотрите внимательно: предложение else принадлежит циклу for, а не оператору if.)

При использовании с циклом предложение else имеет больше общего с предложением else оператора try, чем с инструкциями if: предложение else оператора try выполняется, когда не возникает исключение, а условие else цикла выполняется, когда перерыв не происходит. Подробнее об операторе try и исключениях см. Обработка исключений.

Оператор continue, также заимствованный из C, продолжает следующую итерацию цикла:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
2 голосов
/ 02 апреля 2012

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

1 голос
/ 21 февраля 2019

Великолепные ответы:

  • это , которые объясняют историю, и
  • это дает правильную цитату для облегчения вашего перевода/understanding.

Моя заметка здесь основана на том, что однажды сказал Дональд Кнут (извините, не могу найти ссылку), что существует конструкция, в которой while-else неотличима от if-else, а именно (в Python):

x = 2
while x > 3:
    print("foo")
    break
else:
    print("boo")

имеет тот же поток (исключая различия низкого уровня), что и:

x = 2
if x > 3:
    print("foo")
else:
    print("boo")

Дело в том, что if-else можно рассматривать как синтаксический сахар для while-else, которыйимеет неявный break в конце своего if блока.Противоположный вывод, что цикл while является расширением до if, более распространен (это просто повторная / циклическая условная проверка), потому что if часто преподается до while.Однако это не так, потому что это означает, что else блок в while-else будет выполняться каждый раз , когда условие ложно.

Чтобы облегчить ваше понимание, подумайте об этом так:

Без break, return и т. Д. Цикл заканчивается только тогда, когда условие больше не выполняется, и в этом случае блок else также будет выполнен один раз.В случае Python for вы должны рассмотреть циклы в стиле C for (с условиями) или перевести их на while.

Еще одно примечание:

Преждевременный break, return и т. Д. Внутри цикла делает невозможным превращение условия в ложное, поскольку выполнение выпрыгнуло из цикла, в то время как условие было истинным, и никогда не вернется, чтобы проверить его снова.

1 голос
/ 25 августа 2018
for i in range(3):
    print(i)

    if i == 2:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

"еще" здесь безумно просто, просто означает

1, «если for clause завершено»

for i in range(3):
    print(i)

    if i == 2:
        print("Too big - I'm giving up!")
        break;
if "for clause is completed":
    print("Completed successfully")

Имеется возможность написать такие длинные операторы, как «предложение завершено», поэтому они вводят «еще».

else здесь, если по своей природе.

2, а как насчет for clause is not run at all

In [331]: for i in range(0):
     ...:     print(i)
     ...: 
     ...:     if i == 9:
     ...:         print("Too big - I'm giving up!")
     ...:         break
     ...: else:
     ...:     print("Completed successfully")
     ...:     
Completed successfully

Так что это полностью утверждение логическая комбинация:

if "for clause is completed" or "not run at all":
     do else stuff

или, скажем так:

if "for clause is not partially run":
    do else stuff

или так:

if "for clause not encounter a break":
    do else stuff
1 голос
/ 02 марта 2018

Вот еще один идиоматический вариант использования помимо поиска. Допустим, вы хотели подождать, пока условие будет выполнено, например, порт, который будет открыт на удаленном сервере, а также некоторое время ожидания. Тогда вы можете использовать конструкцию while...else, например, так:

import socket
import time

sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
    if sock.connect_ex(('127.0.0.1', 80)) is 0:
        print('Port is open now!')
        break
    print('Still waiting...')
else:
    raise TimeoutError()
0 голосов
/ 05 мая 2019

Python использует циклы else after for и while, так что если к циклу ничего не применяется, происходит что-то еще. Например:

test = 3
while test == 4:
     print("Hello")
else:
     print("Hi")

Вывод будет «Привет» снова и снова (если я прав).

0 голосов
/ 13 февраля 2019

Я рассматриваю структуру как для (если) A и B, а для (если) - еще специальное if-else , примерно . Это может помочь понять иначе .

A и B выполняются не более одного раза, что аналогично структуре if-else.

for (if) может рассматриваться как специальное условие if, которое выполняет цикл для выполнения условия if. После выполнения условия , если , A и break ; Остальное , B.

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