При всем при том, при всем при том, пускай бедны мы с вами…
Роберт Бёрнс. Честная бедность
Проверки с помощью if, elif и else выполняются последовательно, одна за другой. Иногда определенные операции требуется выполнить более чем один раз. Для этого нужен цикл, и Python предлагает два варианта: while и for.
Самым простым циклическим механизмом в Python является while. Попробуйте запустить с помощью интерактивного интерпретатора следующий пример — это простейший цикл, который выводит на экран значения от 1 до 5:
>>> count = 1
>>> while count <= 5:
... print(count)
... count += 1
...
1
2
3
4
5
>>>
Сначала мы присваиваем значение 1 переменной count. Цикл while сравнивает значение переменной count с числом 5 и продолжает работу, если значение переменной count меньше или равно 5. Внутри цикла мы выводим значение переменной count, а затем увеличиваем его на 1 с помощью выражения count+=1. Python возвращается к началу цикла и снова сравнивает значение переменной count с числом 5. Значение переменной count теперь равно 2, весь цикл while проходит очередной раз, и затем переменная count увеличивается до 3.
Так продолжается до тех пор, пока переменная count не будет увеличена с 5 до 6 в нижней части цикла. Во время очередного возвращения к началу цикла проверка count<=5 вернет значение False и цикл while закончится. Python перейдет к выполнению следующих строк.
Если вы хотите, чтобы цикл выполнялся до тех пор, пока что-то не произойдет, однако вы не знаете точно, когда это событие случится, можно воспользоваться бесконечным циклом, содержащим оператор break. В этот раз мы прочитаем строку с клавиатуры с помощью функции input(), а затем выведем ее на экран, сделав первую букву прописной. Цикл прервется, когда будет введена строка, содержащая только букву q:
>>> while True:
... stuff = input("String to capitalize [type q to quit]: ")
... if stuff == "q":
... break
... print(stuff.capitalize())
...
String to capitalize [type q to quit]: test
Test
String to capitalize [type q to quit]: hey, it works
Hey, it works
String to capitalize [type q to quit]: q
>>>
Иногда вам нужно не прерывать весь цикл, а пропустить по какой-либо причине только одну итерацию. Рассмотрим пример: прочитаем целое число, и если оно четное, выведем на экран его значение в квадрате, если же нечетное — пропустим его. Мы даже добавим несколько комментариев. И вновь для выхода из цикла используем строку q:
>>> while True:
... value = input("Integer, please [q to quit]: ")
... if value == 'q': # выход
... break
... number = int(value)
... if number % 2 == 0: # нечетное число
... continue
... print(number, "squared is", number*number)
...
Integer, please [q to quit]: 1
1 squared is 1
Integer, please [q to quit]: 2
Integer, please [q to quit]: 3
3 squared is 9
Integer, please [q to quit]: 4
Integer, please [q to quit]: 5
5 squared is 25
Integer, please [q to quit]: q
>>>
Если цикл while завершился нормально (без вызова break), управление передается в опциональный блок else. Вы пользуетесь этим, когда кодируете цикл так, чтобы, выполняя некоторую проверку, он прервался, как только проверка успешно выполнится. Блок else запустится в том случае, если цикл while пройдет полностью, но искомый объект так и не будет найден:
>>> numbers = [1, 3, 5]
>>> position = 0
>>> while position < len(numbers):
... number = numbers[position]
... if number % 2 == 0:
... print('Found even number', number)
... break
... position += 1
... else: # break не вызываем
... print('No even number found')
...
No even number found
Такое использование ключевого слова else может показаться нелогичным. Воспринимайте его как проверку на прерывание цикла.
В Python итераторы часто используются по одной простой причине. Они позволяют вам проходить структуры данных без знания того, насколько эти структуры велики и как реализованы. Вы даже можете обратиться к данным, которые были созданы во время работы программы. Это позволяет обрабатывать потоки данных, которые в противном случае не поместились бы в память компьютера.
Чтобы продемонстрировать итерирование, нам нужно что-то, по чему можно проитерировать. Вы уже познакомились со строками в главе 5, но пока не знаете всей информации о других итерабельных объектах, таких как списки и кортежи (глава 7) или словари (глава 8). Сейчас я покажу два способа итерирования по строке, а итерирование по другим типам рассмотрим в соответствующих главах.
Вполне возможно пройти по строке таким образом:
>>> word = 'thud'
>>> offset = 0
>>> while offset < len(word):
... print(word[offset])
... offset += 1
...
t
h
u
d
Однако существует более характерный для Python способ решения этой задачи:
>>> for letter in word:
... print(letter)
...
t
h
u
d
Итерирование по строке возвращает один символ за раз.
Оператор break прерывает цикл for точно так же, как и цикл while.
>>> word = 'thud'
>>> for letter in word:
... if letter == 'u':
... break
... print(letter)
...
t
h
Добавление ключевого слова continue в цикл for позволяет перейти на следующую итерацию цикла, как и в случае с циклом while.
Как и в цикле while, в for имеется опциональный блок else, который проверяет, выполнился ли цикл for полностью. Если ключевое слово breakне было вызвано, будет выполнен блок else.
Это полезно в тех случаях, когда вам нужно убедиться в том, что предыдущий цикл выполнился полностью, а не был прерван break.
>>> word = 'thud'
>>> for letter in word:
... if letter == 'x':
... print("Eek! An 'x'!")
... break
... print(letter)
... else:
... print("No 'x' in there.")
...
t
h
u
d
No 'x' in there
Как и в цикле while, в цикле for использование блока else может показаться нелогичным. Можно рассматривать цикл for как поиск чего-либо, а появление else — как сигнал, что вы ничего не нашли. Чтобы получить тот же эффект без блока else, используйте переменную, которая будет показывать, нашелся ли искомый элемент в цикле for.
Функция range() выбирает поток чисел в заданном диапазоне без необходимости создавать и сохранять крупную структуру данных, такую как список или кортеж. Это позволяет создавать большие диапазоны, не используя всю память на вашем компьютере и не сбивая программу.
Функцию range() можно применять так же, как функцию slice(): range(начало,конец,шаг). Если вы опустите значение начало, диапазон начнется с 0. Обязательным является только значение конец: как и в случае со slice(), последнее учтенное значение будет прямо перед конец. Значение по умолчанию шаг равно 1, но вы можете изменить его на –1.
Как и zip(), функция range() возвращает итерабельный объект, поэтому вам нужно пройти по значениям с помощью конструкции for...in или преобразовать объект в последовательность, такую как список. Создадим диапазон 0, 1, 2:
>>> for x in range(0,3):
... print(x)
...
0
1
2
>>> list(range(0, 3))
[0, 1, 2]
Вот так можно создать диапазон от 2 до 0:
>>> for x in range(2, -1, -1):
... print(x)
...
2
1
0
>>> list(range(2, -1, -1))
[2, 1, 0]
В следующем фрагменте кода шаг равен 2, что позволяет получить все четные числа от 0 до 10:
>>> list(range(0, 11, 2))
[0, 2, 4, 6, 8, 10]
В главе 14 рассматривается итерирование по файлам. В главе 10 вы увидите, как использовать итерирование для объектов, которые вы сами определили. В главе 11 мы рассмотрим itertools — стандартный модуль Python, содержащий множество удобных функций.
В следующей главе мы объединим индивидуальные объекты в списки и кортежи.
6.1. Используйте цикл for, чтобы вывести на экран значения списка [3,2,1,0].
6.2. Присвойте значение 7 переменной guess_me и значение 1 переменной number. Напишите цикл while, который сравнивает переменные number и guess_me. Выведите строку 'toolow', если значение переменной start меньше значения переменной guess_me. Если значение переменной number равно значению переменной guess_me, выведите строку 'foundit!' и выйдите из цикла. Если значение переменной number больше значения переменной guess_me, выведите строку 'oops' и выйдите из цикла. Увеличьте значение переменной number на выходе из цикла.
6.3. Присвойте значение 5 переменной guess_me. Используйте цикл for для того, чтобы проитерировать с помощью переменной number по диапазону range(10). Если значение переменной number меньше, чем значение guess_me, выведите на экран сообщение 'toolow'. Если оно равно значению guess_me — выведите сообщение 'foundit!', а затем выйдите из цикла. Если значение переменной number больше, чем guess_me, выведите на экран сообщение 'oops' и выйдите из цикла.