Цикл while в Python: break, continue и else
Обновлено:
В первой части мы познакомились с базовой конструкцией:
while condition:
...
Теперь посмотрим, как внутри while использовать:
if
elif
else
input()
а также познакомимся с:
break
continue
и конструкцией:
while ...:
...
else:
...
while вместе с input()
1. Цикл может постоянно запрашивать данные
Например, программа собирает числа пользователя и складывает их.
Пока мы ещё не знаем break, можно заранее создать специальное значение:
user_input = None
total = 0
while user_input != 'exit':
user_input = input(
'Введите число или exit: '
).strip()
if user_input.removeprefix('-').isdecimal():
number = int(user_input)
total += number
elif user_input != 'exit':
print('Введите целое число')
print(f'Сумма: {total}')
Пользователь может вводить:
Введите число или exit: 10
Введите число или exit: 25
Введите число или exit: -5
Введите число или exit: exit
Результат:
Сумма: 30
2. Почему заранее создаём user_input
В условии:
while user_input != 'exit':
имя:
user_input
должно существовать уже при первой проверке условия.
Поэтому заранее пишем:
user_input = None
Первая проверка:
None != 'exit'
даёт:
True
и цикл начинается.
Позже мы познакомимся с break, который позволяет решить эту задачу проще.
Добавление значений в список
3. Ещё один пример
Программа собирает названия технологий:
technology = None
technologies = []
while technology != 'exit':
technology = input(
'Введите технологию или exit: '
).strip()
if technology == 'exit':
print('Ввод завершён')
elif technology:
technologies.append(technology)
print(technologies)
Например:
Введите технологию или exit: Python
Введите технологию или exit: SQL
Введите технологию или exit: Django
Введите технологию или exit: exit
Получим:
['Python', 'SQL', 'Django']
Строка:
exit
в список не добавилась.
Проверка пароля
4. Повторяем ввод до правильного значения
password = 'python123'
user_password = None
wrong_attempts = 0
while user_password != password:
user_password = input(
'Введите пароль: '
)
if user_password != password:
wrong_attempts += 1
print('Неверный пароль')
print('Пароль верный')
print(
f'Неверных попыток: {wrong_attempts}'
)
Пока пароль неправильный, условие:
user_password != password
остаётся True.
Как только строки совпали, при следующей проверке условие становится:
False
и цикл заканчивается.
Обход цифр целого числа
5. Последняя цифра
Мы уже знаем:
number % 10
позволяет получить последнюю цифру положительного целого числа.
Например:
number = 5837
last_digit = number % 10
print(last_digit)
Результат:
7
А:
number // 10
позволяет убрать последнюю цифру:
number = 5837
number = number // 10
print(number)
Результат:
583
6. Обходим все цифры
number = 5837
while number > 0:
digit = number % 10
print(digit)
number //= 10
Результат:
7
3
8
5
Мы получаем цифры справа налево.
7. Как работает алгоритм
Начинаем:
5837
Первая итерация:
5837 % 10 → 7
5837 // 10 → 583
Вторая:
583 % 10 → 3
583 // 10 → 58
Дальше:
58 % 10 → 8
58 // 10 → 5
5 % 10 → 5
5 // 10 → 0
После этого:
number > 0
становится False.
8. Можно собирать цифры в список
number = 5837
digits = []
while number > 0:
digit = number % 10
digits.append(digit)
number //= 10
print(digits)
Результат:
[7, 3, 8, 5]
Цифры находятся в обратном порядке, потому что мы каждый раз забирали последнюю.
Для отрицательного числа перед таким алгоритмом можно работать с:
abs(number)
Отдельно нужно учитывать число 0, потому что условие:
while number > 0:
для него сразу будет False.
randint()
9. Случайное целое число
В модуле:
random
есть функция:
randint()
Например:
from random import randint
number = randint(1, 10)
print(number)
При разных запусках можно получить:
3
или:
8
или:
10
и так далее.
10. Обе границы включаются
Вызов:
randint(1, 10)
может вернуть любое целое число:
1, 2, 3, ..., 9, 10
То есть включаются:
1
и:
10
break
11. Немедленный выход из цикла
Ключевое слово:
break
полностью завершает ближайший цикл.
Например:
from random import randint
count = 0
while count < 10:
number = randint(1, 10)
print(number)
count += 1
if number == 5:
break
Здесь возможно два варианта завершения цикла.
Первый:
count достиг 10
Второй:
randint() вернул 5
↓
break
↓
немедленный выход
12. break не ждёт следующей проверки while
Например:
while count < 10:
...
if number == 5:
break
print('Конец итерации')
Если:
number == 5
выполняется:
break
и Python сразу покидает цикл.
Строка:
print('Конец итерации')
в этой итерации уже не выполнится.
Пароль с break
13. Код становится проще
Раньше:
password = 'python123'
user_password = None
while user_password != password:
user_password = input(
'Введите пароль: '
)
if user_password != password:
print('Неверный пароль')
Теперь можно написать:
password = 'python123'
wrong_attempts = 0
while True:
user_password = input(
'Введите пароль: '
)
if user_password == password:
break
wrong_attempts += 1
print('Неверный пароль')
print('Пароль верный')
print(
f'Неверных попыток: {wrong_attempts}'
)
Нам больше не нужно заранее создавать:
user_password = None
Цикл специально делаем бесконечным:
while True:
и самостоятельно определяем момент выхода:
if user_password == password:
break
continue
14. Пропустить остаток текущей итерации
continue не завершает весь цикл.
Оно завершает только текущую итерацию и сразу возвращает выполнение к следующей проверке while.
Например:
number = 0
while number < 10:
number += 1
if number == 5:
continue
print(number)
Результат:
1
2
3
4
6
7
8
9
10
Число:
5
не было напечатано.
15. Как работает continue
Когда:
number == 5
Python встречает:
continue
и не выполняет оставшуюся часть тела:
print(number)
Вместо этого сразу переходит к:
while number < 10:
и начинает следующую итерацию.
Важно с изменением счётчика
16. continue может случайно создать бесконечный цикл
Например:
number = 0
while number < 10:
if number == 5:
continue
number += 1
Когда number станет:
5
выполнится:
continue
Строка:
number += 1
будет пропущена.
На следующей итерации number всё ещё:
5
Снова выполняется continue.
Получаем бесконечный цикл.
Поэтому всегда важно проверять:
Не пропускает ли
continueизменение значения, от которого зависит завершениеwhile.
Пример с randint() и continue
17. Пропускаем определённое случайное число
from random import randint
count = 0
while count < 10:
count += 1
number = randint(1, 10)
if number == 7:
continue
print(number)
Здесь выполняется ровно до десяти генераций.
Если выпала:
7
мы просто не печатаем её и переходим к следующей итерации.
Важно, что:
count += 1
выполняется до continue.
Поэтому счётчик всё равно движется к завершению цикла.
else у while
18. else можно написать на одном уровне с while
while condition:
...
else:
...
Этот else связан именно с циклом.
Он выполняется, если цикл закончился обычным способом — потому что условие while стало ложным.
19. Пример с randint()
from random import randint
count = 0
while count < 10:
number = randint(1, 10)
print(number)
count += 1
if number == 5:
print('Нашли 5')
break
else:
print(
'За 10 попыток число 5 '
'не выпало'
)
Здесь есть два варианта.
Выпало 5
...
5
Нашли 5
Выполняется:
break
Поэтому блок:
else:
не выполняется.
5 не выпало
После десяти итераций:
count < 10
становится:
False
Цикл заканчивается обычным способом.
Тогда выполняется:
else:
и программа печатает:
За 10 попыток число 5 не выпало
Главное правило while ... else
20. else связан с отсутствием break
Можно запомнить:
цикл закончился без break
→ else выполняется
цикл закончился через break
→ else пропускается
Именно поэтому else у цикла особенно полезен в задачах поиска.
Практический пример break + else
21. Поиск значения
numbers = [
10,
25,
30,
47,
60,
]
index = 0
while index < len(numbers):
if numbers[index] == 47:
print(
f'Найден индекс: {index}'
)
break
index += 1
else:
print('Значение не найдено')
Если 47 найдено:
Найден индекс: 3
else не выполняется.
Если удалить 47 из списка, цикл закончится потому, что:
index < len(numbers)
станет False.
Тогда:
Значение не найдено
break, continue и else
Коротко:
break
→ полностью выйти из цикла
continue
→ закончить только текущую итерацию
и перейти к следующей
while ... else
→ выполнить else,
если цикл завершился без break
Обход списка с помощью while
22. От начала к концу
fruits = [
'apple',
'banana',
'orange',
'mango',
]
index = 0
fruits_length = len(fruits)
while index < fruits_length:
print(
fruits[index]
)
index += 1
Результат:
apple
banana
orange
mango
23. Как работает обход
Начинаем:
index = 0
Получаем:
fruits[0]
Затем:
index += 1
и получаем:
fruits[1]
Дальше:
fruits[2]
fruits[3]
Когда:
index == 4
условие:
index < fruits_length
становится:
4 < 4 → False
Цикл заканчивается.
Такой же принцип работает со строкой
24. Обход по индексам
word = 'Python'
index = 0
word_length = len(word)
while index < word_length:
print(word[index])
index += 1
Результат:
P
y
t
h
o
n
Тот же принцип можно использовать для других объектов, поддерживающих индексацию.
Обход в обратном порядке
Возьмём:
fruits = [
'apple',
'banana',
'orange',
'mango',
]
Разберём три способа.
25. Способ №1. Отрицательный индекс через положительный счётчик
index = 1
while index <= len(fruits):
print(
fruits[-index]
)
index += 1
Получаем:
mango
orange
banana
apple
Используются индексы:
-1
-2
-3
-4
26. Способ №2. Положительные индексы справа налево
index = len(fruits) - 1
while index >= 0:
print(
fruits[index]
)
index -= 1
Сначала вычисляем индекс последнего элемента:
len(fruits) - 1
Для четырёх элементов:
4 - 1 = 3
Дальше:
3
2
1
0
27. Способ №3. Только отрицательные индексы
index = -1
while index >= -len(fruits):
print(
fruits[index]
)
index -= 1
Получаем индексы:
-1
-2
-3
-4
и снова обходим список от последнего элемента к первому.
Нужно ли каждый раз вызывать len()
28. Два варианта
Можно написать:
index = 0
while index < len(values):
index += 1
Функция:
len(values)
будет вызываться при каждой проверке условия.
Можно заранее сохранить длину:
index = 0
values_length = len(values)
while index < values_length:
index += 1
Теперь len() вызывается только один раз.
29. Небольшой эксперимент
from timeit import timeit
values = range(5_000)
def solve1(items):
index = 0
while index < len(items):
index += 1
def solve2(items):
index = 0
items_length = len(items)
while index < items_length:
index += 1
print(
timeit(
lambda: solve1(values),
number=30_000,
)
)
print(
timeit(
lambda: solve2(values),
number=30_000,
)
)
Второй вариант может оказаться быстрее, потому что:
len(items)
не вызывается при каждой итерации.
Конкретная разница зависит от:
- версии Python;
- компьютера;
- типа объекта;
- количества итераций.
Поэтому нельзя рассчитывать на универсальное правило вроде:
всегда ровно в два раза быстрее
30. Когда длину удобно сохранять заранее
Если длина объекта во время цикла не должна изменяться, запись:
items_length = len(items)
может быть полезна:
- меньше повторяющихся вызовов;
- условие становится проще;
- явно видно, с какой длиной работает алгоритм.
Например:
fruits_length = len(fruits)
while index < fruits_length:
...
31. Когда нужно быть осторожным
Если внутри цикла сам список изменяет длину:
items.append(...)
или:
items.pop()
заранее сохранённое:
items_length
уже может не соответствовать текущему:
len(items)
Поэтому решение зависит от алгоритма.
Главное по второй части
Внутри while можно использовать обычные конструкции Python:
input()
if
elif
else
Например:
while condition:
value = input(...)
if ...:
...
elif ...:
...
else:
...
break полностью завершает цикл:
if condition:
break
continue завершает только текущую итерацию:
if condition:
continue
При использовании continue важно не пропустить изменение переменной, от которой зависит завершение while.
Конструкция:
while condition:
...
else:
...
работает так:
выход без break → else выполняется
выход через break → else не выполняется
С помощью while можно обходить объекты по индексам:
index = 0
items_length = len(items)
while index < items_length:
print(
items[index]
)
index += 1
В обратном направлении можно использовать как положительные, так и отрицательные индексы.
Функцию len() можно сохранить заранее:
items_length = len(items)
если длина объекта во время обхода не изменяется.