2.13. Управление циклом

Два ключевых слова меняют то, как выполняется цикл:

  • break – немедленно выйти из цикла.

  • continue – пропустить остаток текущей итерации и перейти к следующей.

Оба относятся к самому внутреннему циклу, внутри которого они находятся.

2.13.1. break

Используйте break, чтобы остановить цикл, как только выполнится условие. Классический шаблон «найти и остановиться»:

found = None
for item in items:
    if matches(item):
        found = item
        break

if found is not None:
    print("found:", found)

В цикле while True: именно break завершает цикл:

while True:
    line = next_line()
    if line == "quit":
        break
    process(line)

2.13.2. continue

Используйте continue, чтобы пропустить остаток тела и перейти к следующей итерации. Удобно для фильтрации элементов внутри цикла:

for n in numbers:
    if n < 0:
        continue            # skip negatives
    print(n)

Тот же эффект можно записать как блок if вокруг остальной части тела. Иногда continue понятнее, когда условие пропуска проще сформулировать заранее, чем условие сохранения.

Внутри цикла continue играет ту же роль, что и ранний return в функции: пропустить случаи, которые вы не обрабатываете, и оставить основную работу на внешнем уровне отступа без вложенности. Цикл фильтрации и обработки – это каноническая форма:

for item in items:
    if item is None:
        continue
    if not item.is_valid():
        continue
    process(item)

Строка с отступом process(item) – это и есть фактическая работа; каждое условие выше точно указывает, какие элементы будут пропущены.

2.13.3. else в цикле

И for, и while допускают необязательный блок else. Он выполняется, когда цикл завершается без срабатывания break. Чаще всего это используется в цикле поиска, которому нужен запасной вариант, если ничего не найдено:

for item in items:
    if matches(item):
        print("found:", item)
        break
else:
    print("no match")

Если срабатывает break, блок else пропускается. Читайте эту конструкцию как «for X in Y: …; а иначе, если мы ни разу не вышли, выполни Z.»

2.13.4. Распространённые шаблоны циклов

Несколько шаблонов часто встречаются в реальных скриптах:

  • Опрос – ждать, пока некоторое условие не станет истинным, прежде чем продолжить. В теле используется pass, оператор-заглушка Python; каждый блок с отступом должен содержать хотя бы один оператор, и pass – это способ сказать «здесь ничего не делать»:

    while not ready():
        pass
    proceed()
    
  • Конечный автомат – единственный цикл while True:, который выбирает, что делать, на основе переменной состояния. Полезно, когда работа чётко разбивается на несколько именованных фаз:

    state = "header"
    for line in lines:
        if state == "header":
            if line.startswith("---"):
                state = "body"
        elif state == "body":
            print(line)
    
  • Накопление – формировать результат при обходе последовательности:

    total = 0
    for x in samples:
        total += x
    mean = total / len(samples)
    

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

    • sum() – складывает каждый элемент итерируемого объекта.

    • max() / min() – наибольший или наименьший элемент.

    • any()True, если хотя бы один элемент истинный.

    • all()True только тогда, когда каждый элемент истинный.

    • sorted() – новый список с элементами по порядку.

    • len() – количество элементов (там, где итерируемый объект знает свою длину).

    >>> samples = [3, 1, 4, 1, 5, 9, 2, 6]
    >>> sum(samples)
    31
    >>> sum(samples) / len(samples)        # mean
    3.875
    >>> max(samples)
    9
    >>> min(samples)
    1
    >>> sorted(samples)
    [1, 1, 2, 3, 4, 5, 6, 9]
    >>> any([False, False, True])
    True
    >>> all([True, True, False])
    False
    

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