Как работает конструкция цикла for-else в Python?

Python поддерживает конструкцию цикла for-else, которая менее известна, чем просто цикл for, но очень полезна.

Если вы программировали на Python, то, вероятно, использовали цикл for для перебора элементов в итерируемых объектах, таких как списки. Но для некоторых случаев может быть полезным использование цикла for в сочетании с else.

В этой статье мы разберем, как использовать цикл for-else, и рассмотрим несколько примеров, чтобы понять, как он работает.

Синтаксис цикла for-else в Python

В Python цикл for-else – это конструкция, которая объединяет цикл for с предложением else. Обычно в цикле проверяется некое условие, и если оно оценивается как True, мы выходим из цикла. Блок else выполняется только тогда, когда цикл for завершается нормально, не встретив оператор break.

Давайте рассмотрим общую конструкцию цикла for-else:

for item in iterable:
    # loop body
    if condition:
        break
else:
    # else body

Вот как этот код работает:

  1. Цикл for перебирает каждый элемент в iterable.
  2. Если условие condition оценивается как True и мы выходим из цикла с помощью оператора break, блок else пропускается.
  3. Если цикл for перебирает все элементы в iterable, но при этом условие выхода из цикла не выполняется, то задействуется блок else.

Теперь давайте разберем несколько примеров.

Проверка числа на простоту с помощью цикла for-else

Давайте воспользуемся циклом for-else, чтобы проверить, является ли число простым. Как вы помните, число является простым, если оно делится только на 1 и на само себя и не имеет других множителей.

Посмотрите на этот код:

import math

def is_prime(n):
    if n <= 1:
        return False
    
    for i in range(2, int(math.sqrt(n))+ 1):
        if n % i == 0:
            print(f"{n} is divisible by {i}. Not a prime number.")
            break
    else:
        # Этот блок выполняется, если цикл не встретил оператор break
        print(f"{n} is a prime number.")
        return True

Сначала функция is_prime() проверяет, меньше или равно единице введенное число n. Если да, то она возвращает False, поскольку простые числа больше 1 (наименьшее простое число – 2).

Далее мы используем цикл for для итерации по диапазону чисел от 2 до квадратного корня из n (включительно).

  • Если n делится без остатка на любое i в диапазоне (2, √n), значит, n не является простым числом, так как мы нашли его множитель. Функция печатает сообщение и выходит из цикла. При этом блок else пропускается.
  • Если цикл завершается, не найдя ни одного множителя и, соответственно, не встретив оператор break, – выполняется блок else. Функция выводит сообщение о том, что n – простое число, и возвращает True.

Вы можете убедиться, что функция is_prime() работает так, как ожидалось, с помощью нескольких вызовов:

# Тест с непростым числом
is_prime(10) 
# Вывод: 10 is divisible by 2. Not a prime number.


# Тест с простым числом
is_prime(13) 
# Вывод: 13 is a prime number.

Замечание о проверке чисел на простоту

Для поиска потенциального множителя числа n кажется естественным запустить цикл по всем числам от 2 до n. Но на самом деле достаточно выполнить итерацию до квадратного корня из n. Почему?

Вспомните, что если p – множитель числа n, то всегда можно найти такое q, что p x q = n:

  • Когда n – полный квадрат, p = q. (Полный квадрат – целое число, квадратный корень из которого извлекается нацело, например, 9 или 25).
  • Когда n не является полным квадратом, получается следующее. Если p меньше √n, то q больше √n. А если q больше √n, то p меньше √n.

Таким образом, если вы не нашли множитель до √n, вы не сможете найти его и после √n.

Поиск элемента в списке с помощью цикла for-else

Рассмотрим еще один пример, в котором пригодится цикл for-else.

Следующая функция search_item() принимает список и элемент. Задача состоит в том, чтобы перебрать список и проверить, содержит ли он указанный элемент. Для решения этой задачи вы можете использовать конструкцию цикла for-else:

def search_item(lst, item):
    for i in lst:
        if i == item:
            print(f"Found {item} in the list.")
            break
    else:
        print(f"{item} is not in the list.")

Если элемент найден, мы выходим из цикла. Блок else срабатывает только в том случае, если элемент не найден в списке.

Давайте проверим это с помощью нескольких вызовов функции:

# Тест со списком, содержащим указанный элемент
search_item([1, 2, 3, 4, 5], 3)  
# Вывод: Found 3 in the list.

# Тест со списком, не содержащим указанный элемент
search_item([1, 2, 3, 4, 5], 6)  
# Вывод: 6 is not in the list.

Подведение итогов

Надеемся, что это руководство по конструкции цикла for-else в Python было вам полезно.

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

Перевод статьи «How Does Python’s For-Else Loop Construct Work?».

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *