- •§0.1. Базовые знания
- •§0.2. Где достать интерпретатор языка Питон?
- •§0.3. Установка интерпретатора языка Питон в unix
- •§0.3.1. Установка/обновление Питона из грт-пакета
- •§0.3.2. Установка Питона из исходного кода
- •§0.4. Установка Питона в ос Windows
- •§0.5. Запуск программ, написанных на Питоне
- •§0.6. Среда разработки
- •§1.1. Алгоритмы и программы
- •§1.2. Языки программирования и уровни абстракции
- •Глава 1. Базовые понятия
- •§1.3. Формальные и естественные языки
- •§1.4. Интерпретаторы и компиляторы
- •§1.5. Первая программа
- •§1.6. Что такое отладка?
- •§1.6.1. Синтаксические ошибки (syntax errors)
- •§1.6.2. Ошибки выполнения (runtime errors)
- •§1.6.3. Семантические ошибки (semantic errors)
- •§1.6.4. Процесс отладки
- •Глава 2. Переменные, операции и выражения
- •§2.1. Значения и типы
- •§2.2. Преобразование типов
- •§2.3. Переменные
- •§2.4. Имена переменных и ключевые слова
- •§2.5. Выражения
- •§2.6. Выполнение выражений
- •§2.7. Операторы и операнды
- •§2.8. Порядок операций
- •§2.9. Простейшие операции над строками
- •§2.10. Композиция
- •Глава 3. Функции §3.1. Подпрограммы
- •§3.2. Вызовы функций
- •§3.3. Справочная система
- •§3.4. Импорт модулей и математические функции
- •§3.5. Композиция
- •§3.6. Создание функций
- •§3.7. Параметры и аргументы
- •§3.8. Локальные переменные
- •§3.9. Поток выполнения
- •§3.10. Стековые диаграммы
- •§3.11. Функции, возвращающие результат
- •Глава 4. Компьютерная графика
- •Глава 5. Логические выражения, условия и рекурсия §5.1. Комментарии в программах
- •§5.2. Простые логические выражения и логический тип данных
- •§5.3. Логические операторы
- •§5.4. Выполнение по условию и «пустота»
- •§5.5. Ввод данных с клавиатуры
- •§5.6. Альтернативные ветки программы (Chained conditionals)
- •§5.7. Пустые блоки
- •§5.8. Вложенные условные операторы (Nested conditionals)
- •§5.9. Рекурсия
- •§5.10. Стековые диаграммы рекурсивных вызовов
- •§5.11. Максимальная глубина рекурсии
- •§5.12. Числа Фибоначчи
- •Глава 6. Циклы
- •§6.1. Оператор цикла while
- •§6.2. Счетчики
- •§6.3. Бесконечные циклы
- •§6.4. Альтернативная ветка цикла while
- •§6.5. Табулирование функций
- •§6.6. Специальные и экранируемые символы
- •§6.7. Числа Фибоначчи и оператор цикла while
- •§6.8. Вложенные операторы цикла и двумерные таблицы
- •§6.9. Классификация операторов цикла
- •§6.10. Управляющие структуры
- •Глава 7. Строки
- •§7.1. Оператор индексирования
- •§7.2. Длина строки и отрицательные индексы
- •§7.3. Перебор и цикл for
- •§7.4. Срезы строк
- •§7.5. Сравнение строк
- •§7.6. Строки нельзя изменить
- •§7.7. Функция find
- •§7.8. Циклы и счётчики
- •§7.9. Модуль string
- •§7.10. Классификация символов
- •§10.2. Операции над словарями
- •§10.3. Методы словарей
- •§10.4. Использование псевдонимов и копирование
- •§10.5. Разряженные матрицы
- •§10.6. Подсказки
- •§10.7. Тип «длинное целое число»
- •§10.8. Подсчет букв
Глава 6. Циклы
§6.1. Оператор цикла while
В предыдущей главе мы столкнулись с необходимостью повторения некоторых блоков кода в процессе выполнения вычислений. В некотором смысле, мы справились с этой проблемой, использовав рекурсию, но ее использование далеко не всегда оправдано. Во-первых, разобраться, как работает рекурсивная функция не так-то просто, а это означает, что расширение функциональности программы будет затруднено, особенно если над ней будет работать не один программист, а целая команда. Во-вторых, рекурсивные функции очень «прожорливы» - для их выполнения требуется много оперативной памяти, да ограничение максимального размера стека вызовов тоже создает некоторые трудности.
Разумеется, не мы первые так подумали. В первой главе мы уже говорили о том, что еще во времена низкоуровневых языков программирования была замечена необходимость в повторах блоков кода. Поэтому все высокоуровневые языки программирования имеют специальные операторы, позволяющие организовывать циклы в программах. Такие операторы обычно так и называют: операторами цикла.
Каждый циклический оператор имеет тело цикла- некий блок кода, который интерпретатор будет повторять пока условие повторения цикла будет оставаться истинным.
В языке Питон оператор цикла выглядит так:
while УСЛОВИЕ_ПОВТОРЕНИЯ_ЦИКЛА: ТЕЛО_ЦИКЛА
Очень похоже на оператор условия - только здесь используется другое ключевое слово: while (англ. «пока»). Где его можно использовать? Первое, что приходит в голову: повтор ввода данных пользователем, пока не будет получено корректное значение:
correct_choice = False
while not correct_choice:
choice = raw_input("Enter your choice, please (1 or 2):")
if choice == "1" or choice == "2":
correct_choice = True
else:
print "Invalid choice! Try again, please."
print "Thank you."
Перед началом цикла мы определили логическую переменную correct_choice, присвоив ей значение False. Затем оператор цикла проверяет условие not correct_choice: отрицание False - истина. Поэтому начинается выполнение тела цикла: выводится приглашение "Enter your choice, please (1 or 2) :" и ожидается ввод пользователя. После нажатия клавиши [Enter] введенное значение сравнивается со строками "1" и "2", и если оно равно одной из них, то переменной correct_choice присваивается значение True. В противном случае программа выводит сообщение "invalid choice ! Try again, please . ". Затем оператор цикла снова проверяет условие и если оно по-прежнему истинно, то тело цикла повторяется снова, иначе поток выполнения переходит к следующему оператору, и интерпретатор выводит строку "Thank you.". Как видите, все довольно просто.
64
Ревизия: 170
Циклы
Упражнение. Наберите программу в файле и поэкспериментируйте с ней: попробуйте вводить различные строки и цифры. Правильно ли работает программа?
§6.2. Счетчики
Еще один вариант использования оператора цикла - вычисление формул с изменяющимся параметром. В одном из упражнений предыдущей главы было задание с
п
помощью рекурсивной функции вычислить формулу 2^,i —I +... + п при заданном п. В
г = 1
данном случае изменяющимся параметром является /', причем /' последовательно принимает значения в диапазоне от 1 до п.
С помощью оператора цикла while решение будет выглядеть так:
n = input("Input n, please:") |
|
|
|
|
sum = 0 |
|
|
|
|
i = 1 |
|
|
|
|
while i <= n: |
|
|
|
|
sum = sum + i**3 #Тоже самое |
можно |
записать |
короче: |
sum += |
i**3 |
|
|
|
|
i = i + 1 #Аналогично |
i += |
1 |
|
|
print "sum = ", sum |
|
|
|
|
Разберемся, как работает эта программа. Сначала пользователь вводит п - граничное значение i. Затем производится инициализация переменных sum (в ней будет храниться результат, начальное значение - 0) и счетчика i (по условию, начальное значение - 1). Далее начинается цикл, который выполняется, пока i <= п. В теле цикла в переменную sum записывается сумма значения из этой переменной, полученная на предыдущем шаге, и значение i, возведенное в куб; счетчику i присваивается следующее значение. После завершения цикла выводится значение s um после выполнения последнего шага.
Следующее значение счетчика получают прибавлением к его текущему значению шага цикла (в данном случае шаг цикла равен 1). Шаг цикла при необходимости может быть отрицательным, и даже дробным. Кроме того, шаг цикла может изменяться на каждой итерации (т.е. при каждом повторении тела цикла).
Теперь давайте попробуем оптимизировать нашу программу. Итак на каждой итерации в теле цикла мы вычисляем следующее значение счетчика. Но на последнем шаге мы вычислем его лишний раз - его новое значение уже использоваться не будет. Конечно, эта операция не требует каких-то особых ресурсов, но привычку обращать внимание на подобные вещи следует вырабатывать, т.к. впоследствии вы, наверняка, будете иметь дело с более сложными операциями. Как избежать выполнения лишнего вычисления? Что если вычислять значение i до вычисления формулы? Давайте попробуем.
n = input("Input n, |
please |
") |
sum = i = 0 |
|
|
while i <= n: |
|
|
65
Ревизия: 170
Циклы
i += 1 |
|
|
sum += |
i**3 |
|
print "sum |
II f |
sum |
Обратите внимание, на запись вида sum = i = 0. Она работает аналогично простому присваиванию значения переменной, но в данном случае обе переменные получают одинаковое начальное значение.
Итак, теперь начальное значение i равно 0, но на первом шаге мы сразу же прибавляем к нему единицу. В результате программа выдает те же результаты, что и предыдущая ее модификация. Изменилось ли количество операций?
Нет, не изменилось, но выглядит, пожалуй, немного изящнее: после завершения цикла i = п. Это может помочь избежать путаницы, если i будет использоваться далее в программе.
Упражнение. Напишите программу, которая с помощью оператора цикла while выводит все четные числа от 0 до заданного пользователем п.
