Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Цикл for Python: Списки

Ранее мы рассматривали цикл while. Эта конструкция предназначена для повторения некоего набора действий — всё, что выходит за рамки "бездумного" повторения, как правило, требует дополнительных средств для хранения состояния. Пример: счётчик, который мы изменяем в цикле. И при работе с коллекциями нам нужно как-то выбирать, с каким элементом мы работаем в текущей итерации. Так что же, использовать переменную-счётчик каждый раз? Любой программист всегда стремится автоматизировать рутинную работу, и авторы языков — не исключение. Поэтому в Python для работы с коллекциями существует другой вид цикла — цикл for.

Стоит сразу отметить, что этот цикл не похож на циклы с тем же названием в других языках программирования. Во многих языках этот цикл всего лишь дополняет условие завершения цикла переменной-счётчиком. Python в стремлении сделать удобно пошёл дальше, поэтому в этом языке цикл for сразу перебирает элементы входной коллекции, и думать об индексе чаще всего вообще не нужно.

Синтаксис

Цикл for устроен очень просто:

for element in collection:
    print(element)  # this is body of cycle

Заметьте, в простейшем случае у цикла даже нет явного условия завершения: цикл просто останавливается, когда в коллекции заканчиваются элементы!

Пример выше сработает для кортежей и списков — в этом случае будут выведены все элементы. А если проитерировать (так называют обход коллекции — позже вы узнаете, почему) строку, то переменная цикла (в коде выше это element) будет поочерёдно содержать все символы строки. Пример:

for c in 'Hello!':
    print(c)

# => H
# => e
# => l
# => l
# => o
# => !

Но что же делать, если нам нужно не просто получить элементы списка один за другим, но и изменить эти элементы? Ведь для этого нам понадобится индекс каждого элемента! На этот случай в Python есть удобная функция enumerate ("пронумеровать"). Эта функция снабжает каждый элемент индексом, складывая каждый индекс вместе с элементом в кортеж. Кортежи эти, как правило, прямо в первой строке цикла и распаковывают:

items = ['foo', 'bar', 'baz']
for (index, elem) in enumerate(items):
    items[index] = elem + '!'

print(items)  # => ['foo!', 'bar!', 'baz!']

В этом цикле мы заменили каждый элемент оригинальным значением, дополненным строкой '!'. Этот код можно было написать и несколько иначе:

items = ['foo', 'bar', 'baz']
for (index, _) in enumerate(items):
    items[index] += '!'

print(items)  # => ['foo!', 'bar!', 'baz!']

В этот раз мы вообще не используем сами элементы — только их индексы. Поэтому вместо переменной цикла, в которую распаковываются элементы, у нас стоит прочерк. Это не какая-то особая переменная, а всего лишь соглашение: в Python часто незначимые в данном контексте вещи "спихивают" в переменную _.

Заметьте: хоть в последнем примере речь и шла об индексах, но мы всё равно не использовали длину коллекции — enumerate тоже знает, где остановиться (в конце исходной коллекции).

Управление циклом с помощью break и continue.

Иногда не нужно доходить до конца коллекции. Пример: поиск элемента, удовлетворяющего некоему условию. Как только мы нашли первый подходящий элемент, нам неплохо бы сэкономить ресурсы и завершить цикл. Такой ранний выход из цикла делается с помощью команды break. Вот цикл поиска первого положительного числа:

items = [-2, 0, -10, 3, 5, -1]
for item in items:
    if item > 0:
        break

print(item)  # => 3

Как вы могли заметить, переменная цикла оказалась доступна и после его завершения. Однако если коллекция окажется пустой, то переменная не будет определена — имейте это в виду!

Этот код, кажется, работает как надо. Однако если в списке не встретится ни одного положительного числа, то в переменной item окажется просто последний элемент списка! Как же понять, что мы ничего не нашли? На помощь приходит else — да, в Python у цикла for тоже есть такая ветка! В цикле else выполняется, если цикл так и не прервался с помощью break. Для алгоритмов поиска — идеальный вариант! Перепишем наш пример с применением else:

items = [-2, 0, -10, -1]
for item in items:
    if item > 0:
        break
else:
    item = None

print(item)  # => None

Победа!

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

lines_of_code = [
    '# begin of example',
    'echo 123',
    'cd foo',
    '# end']
for line in lines_of_code:
    if line[:1] == '#':
        continue
    # here we process a code
    print(line)

# => echo 123
# => cd foo

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

break, continue, else и цикл while

Да, и ветка else, и команды break и continue — доступны и для цикла while! Вот комплексный пример, демонстрирующий все эти возможности:

tries = 3
while tries:
    print('>>> ', end='')
    command = input()
    if not command:
        continue
    if command in ('echo', 'cd', 'help'):
        break
    print('Unknown command!')
    tries -= 1
else:
    print('Too many bad tries!')
    command = None

Этот код просит пользователя ввести одну из команд, игнорирует пустой ввод, ограничивает кол-во попыток ввода. Подумайте, какая часть тела цикла за что отвечает.

Цикл for и изменяемые коллекции

Хочу вас предостеречь от изменения состава списка во время обхода его же в цикле for. Если вы будете удалять элементы из списка, по которому проходитесь — или даже всего лишь добавлять новые элементы в конец — результат может быть неожиданным, вплоть до завершения программы с ошибкой! Лучше наполнять новый список в процессе обхода старого.

Если же вы хотите обязательно изменить состав исходного списка (объекта по ссылке), то либо обходите в цикле копию списка

for x in original_list[:]:
    original_list.pop(0)  # и т.п.

либо создайте временный список, а потом очистите исходный и добавьте элементы из временного

new_list = []
for x in original_list:
    ...
original_list[:] = []  # удаляем старое содержимое
original_list.extend(new_list)

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


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

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

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
Разработка веб-приложений на Django
1 июня 10 месяцев

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»