Синтаксис
Цикл for
python — есть средство для перебора последовательностей
Цикл 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
. В цикле 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_count = 3 while tries_count: print('>>> ', end='') command = input() if not command: continue if command in ('echo', 'cd', 'help'): break print('Unknown command!') tries_count -= 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)
Предыдущий разделСледующий раздел