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
    

    Вбудований варіант коротший, зрозуміліший і зазвичай швидший, ніж написання аналогічного циклу вручну.