Циклы в Ruby— Ruby Rush
В этом уроке мы познакомимся с циклами, научимся их создавать и совершать действия с каждым элементом массива.
Мы научимся создавать с помощью конструкций while
и for-in
, узнаем, что такое тело цикла, а также научимся поочерёдно обрабатывать в цикле элементы массива, вводить данные с консоли и узнаем о команде break
.
План урока
- Что такое циклы, какие бывают, как их создавать и зачем они нужны
- Работа с массивами и переменными в циклах
Что такое циклы
Если вспомнить наш образ дороги из 6-го урока, то иногда на нашей дороге машину нужно пустить по кругу. Например, если нам надо, чтобы грузовик загрузился углём в одном месте, доехал до другого и разгрузилась там и потом повторил всё это, скажем, 7 раз.
Более бытовой пример, с яйцами: вы купили в магазине десяток яиц, принесли их домой и вам нужно разложить их по специальным ячейкам на дверце вашего холодильника, для этого вам нужно будет взять каждое яйцо и положить его в нужную ячейку.
Именно для таких повторяющихся действий в программах используются циклы.
Цикл «while»
Оператор while
нужен для того, чтобы сделать самый простой и универсальный цикл. Такой оператор есть в любом языке программирования.
Все, что он делает — повторяет указанный набор инструкций столько раз, сколько нужно. А сколько именно — зависит от условия цикла.
В этом смысле while
очень похож на if
, но в отличие от if
условие будет проверяться каждый раз перед выполнением очередного повторения.
Сейчас вы все поймете на наглядном примере:
count = 1 while count <= 5 do puts count count += 1 sleep 0.5 end puts "я иду искать!"
Наша программа запишет в переменную
целое число 1
и приступит к циклу.
Сначала программа проверит условие (count <= 5
, клювик-равно означает «меньше или равно»), которое конечно будет выполнено, ведь в count
сейчас лежит 1.
Так как условие выполнено, программа «войдёт» в цикл и начнёт выполнять всё, что написано между while
и end
. Этот блок называется «тело цикла».
Оператор += (сложение с присваиванием)
В теле цикла появился новый для нас оператор +=
:
count += 1
Это очень простая штука. Эта запись эквивалентна записи
count = count + 1
То есть, оператор +=
говорит «сложить текущее значение переменной с тем, что следует за мной, и записать новое значение в ту же переменную». В нашем случае за оператором идёт единица.
Итак, после выполнения действий в теле цикла в первый раз, программа выведет на экран текущее значение count
(1), увеличит это значение на 1 и потом «заснёт» на полсекунды.
А после этого снова проверит условие цикла. Теперь count
равен 2 и поэтому условие снова выполнится. Так будет происходить 5 раз для значений count
1,2,3,4,5 и в последнем заходе count
станет равным шести, а это уже больше пяти и условие в шестой раз не выполнится.
Программа выйдет из цикла и пойдёт дальше после слова end
.
И выведет на экран строчку "Я иду искать!"
Бесконечный (слепой) цикл
Будьте очень аккуратны с циклами! Если вы в предыдущей программе случайно перепутаете условие, поставив например,
while count > 0
то условие цикла всегда будет выполнено и программа будет «крутиться» вечно. Если вдруг такое произошло, чтобы выйти из программы, нажмите в консоли во время её выполнения комбинацию клавиш
.
Эта комбинация досрочно прерывает любую программу, которая в данный момент выполняется в командной строке (или терминале).
Цикл «for in»
Циклы очень удобны для выполнения повторяющихся операций с массивами. С массивами настолько часто работают с помощью циклов, что во многих языках придумали отдельный специальный цикл.
ОН делается с помощью конструкции «for in» и его главное предназначение — перебирать все элементы какого-нибудь массива. Цикл «for in» устроен следующим образом:
array = [1,2,3,4,5] for item in array do puts item end
Разберём каждое слово в этой конструкции.
Начнём с for
. Это служебное слово, которое говорит программе, что мы начинаем описывать цикл, в любой программе цикл «for in» будет начинаться с этого слова.
item
— это особый ярлычок, так называемая внутренняя переменная цикла.
Рассматривайте ее как обычную переменную, с той важной разницей, что видна она только в теле цикла (внутри цикла). За пределами цикла она не видна (ее как будто не существует) и использовать её вне цикла нельзя.
Так же как и обычная переменная имя этой вы можете задать сами (вместо item
можно написать element
и т. п.).
И как для обычных переменных — следите, чтобы имя этой внутренней переменной цикла не пересекалось с другими переменными вашей программы. Будьте аккуратны с выбором названий переменных. Это общее правило для всех ваших программ.
Вернемся к нашему циклу. На каждой итерации (каждом повторении) цикл будет брать каждый элемент из массива array
, и по очереди, начиная с нулевого (помним, что в массивах нумерация начинается с нуля) — записывать в переменную
этот элемент.
Следующее слово в нашем цикле тоже служебное in
, после него идёт тот самый массив, элементы которого циклу предстоит поочерёдно перебирать.
И наконец, дальше идёт переменная array
, в которой содержится массив. Именно из этого массива будут браться элементы для поочерёдного укладывания их в переменную item
, которая в теле цикла будет выводится на экран с помощью команды puts item
.
Ну и, наконец, end
заканчивает тело цикла точно также, как это было в цикле «while».
Если «перевести» это на русский язык, получится как-то так:
Для штуки в массиве выведи штуку закончи
Согласитесь, довольно наглядно
Ввод данных в цикле
Продемонстрируем всю мощь циклов и массивов с помощью простого примера — сбора данных в цикле. Напишем программку «Кто такая Элис?».
Задача программы — обыграть сюжет известной песни «А кто такая Элис?»: спросить у пользователя в цикле массив имен и затем вывести поочередно эти имена в определенных фразах. Но прерваться, если встретится имя Элис и расспросить пользователя подробнее о том, кто же она такая.
https://youtube.com/watch?v=C0-4U2nTYFQ
Для начала как обычно в папке урока lesson7
создадим файлик alice.rb
.
В нем создадим пустой массив names
и воспользуемся знакомыми нам по урокам 5 и 6 командами gets
и push
, чтобы наполнять массив данными, которые пользователь введёт с помощью консоли.
names = [] user_input = nil while user_input != "" do user_input = gets. encode("UTF-8").chomp names << user_input end
Как только пользователь введёт пустое имя (дважды нажмёт Enter
), мы будем считать, что пользователь закончил ввод имён (это условие стоит после слова while
в описании нашего цикла).
После этого мы переберём все введённые имена с помощью цикла «for in» и выведем их на экран в виде песенки:
С нами Миша С нами Вадим ..
А если вдруг увидим слово «Элис» (именно такое условие стоит в условии оператора if
), удивимся и спросим: «Элис?? Кто такая Элис?».
for item in names do puts "C нами " + item sleep 1 if (item == "Элис") puts "Элис??? Кто такая Элис?" sleep 1 break end end puts "Что это за девочка и где она живет?" sleep 1 puts "А вдруг она не курит? А вдруг она не пьёт?" sleep 1 puts "А мы с такими рожами возьмем да и припрёмся к Элис... :)"
Команда break
Обратите внимание, что в блоке «if-end» стоит команда break
.
break
— очень полезная команда для досрочного выхода из цикла. Если нет возможности дождаться окончания текущей итерации, чтобы заново проверилось условие цикла.
Чтобы запустить нашу программу alice.rb
, нужно перейти в вашей консоли в папку урока и запустить её с помощью привычных нам команд:
cd c:\rubytut\lesson7 ruby alice.rb
Итак, в этом уроке мы научились создавать циклы, разобрали создание циклов с помощью конструкций «while» и «for in». Научились в цикле работать с массивами, вводить данные с консоли и узнали о команде break
.
В следующем уроке с использованием всех полученных ранее данных мы напишем игрушку тест на ревнивость и научимся ещё одному способу ввода данных в программу.
Подробный разбор цикла while в Python
Цикл — это некий набор инструкций. Он выполняется до тех пор, пока его условие истинно. Давайте разберемся, как работает цикл while
в Python.
Что такое цикл?
Циклы — фундаментальное понятие в программировании. Если вы новичок, то обязаны в них разобраться. Циклы могут помочь выполнять набор инструкций до тех пор, пока заданное условие истинно.
В Python есть два основных вида циклов:
- Цикл for.
- Цикл while.
Они очень похожи друг на друга. Но если вы хотите писать по-настоящему быстрый код, вам нужно научиться грамотно выбирать нужный цикл.
Цикл while
Суть работы цикла
очень проста. Работает он так: ваши инструкции выполняются, пока условие истинно.
Цикл while
проверяет условие перед каждой итерацией цикла. Если возвращается True
, то выполняется блок кода внутри цикла.
Прежде чем мы возьмемся за написание кода, взгляните на блок-схему. Работает цикл следующим образом:
А теперь напишем небольшую программу. Это простой цикл, выводящий в консоль числа от 1 до 10.
x = 1 while x <= 10: print(x) x = x+1
Как вы можете заметить, тело цикла выполняется, пока x
меньше или равно 10. Если вы присвоите x
значение 20, то цикл не запустится вообще.
Вывод будет следующим:
1 2 3 4 5 6 7 8 9 10
Цикл do-while
Есть две вариации цикла while
. Первая — непосредственно сам while
, вторая — do-while
. Разница заключается в том, что do-while запустится хотя бы один раз.
Цикл while
может не запуститься вообще, если условие не будет истинным изначально. Do-while
— напротив. Тут сначала выполняется тело цикла, и только потом происходит проверка условия.
Цикл do-while
реализован в большинстве языков программирования, но в Python такого оператора нет. Тем не менее, его можно с легкостью имитировать — например, с помощью функций.
Давайте напишем код, имитирующий цикл do-while
. Все нужные инструкции мы поместим внутри функции.
x = 20 def run_commands(x): print(x) run_commands(x) x += 1 while x <= 10: run_commands(x) x += 1
Эта программа запускает run_commands()
еще до цикла while
. Но сам цикл while
не запустится: x
равен 20.
Оператор else
Если вы хотите выполнить блок кода, когда проверка условия возвращает False
, — добавьте оператор else
.
Добавим в наш код else
. Внутри этого блока напишем код, который будет выводить в консоль Готово
. Выполнится этот блок только после того, как в консоль выведутся числа от 1 до 10.
x = 1 while x <= 10: print(x) x = x + 1 else: print("Готово")
Эта программа выведет в консоль числа от 1 до 10. Как только x
станет равно 11, результатом проверки условия будет False
. После этого выполнится блок кода else
.
Однострочное объявление while
Если внутри цикла while
у вас только одна строка — можно воспользоваться однострочным вариантом. Делается это так:
x = 1 while x: print(x)
Будьте осторожны — этот цикл бесконечный.
Бесконечные циклы
Если вы не будете осторожны, то можете случайно написать бесконечный цикл. Проверка условия бесконечного цикла всегда будет возвращать True
. Пример бесконечного цикла:
x = 1 while x >= 1: print(x)
Этот цикл — бесконечный. Внутри цикла нет команды, которая изменяет значение x
. Поэтому условие x >= 1
всегда истинно. Именно из-за этого цикл будет запускаться бесконечное количество раз.
Всегда будьте внимательны, когда создаете цикл. Небольшая ошибка — и у вас бесконечный цикл, что в конечном итоге приведет к сбою в работе программы.
Управление циклом
С циклом разобрались. Наконец мы можем перейти к операторам его управления.
Когда вы начнете работать в реальных проектах, вы будете сталкиваться с разными ситуациями. Например, когда нужно добавить условие, выполнение которого завершит цикл или пропустит итерацию.
Break
Этот оператор позволяет завершить цикл, если проверка условия возвращает True
.
x = 1 while x <= 10: if x == 5: break print(x) x += 1
Вывод:
1 2 3 4
Выполнение цикла прекращается, когда x становится равно 5 — даже если x
больше или равно 1.
Continue
Допустим, вам нужно пропустить итерацию цикла, если выполняется какое-то условие. Но цикл вы не хотите завершать до тех пор, пока проверка его условия не вернет False
.
В этом случае вам нужно использовать ключевое слово continue
:
x = 1 while x <= 10: if x == 5: x += 1 continue print(x) x += 1
Вывод:
1 2 3 4 6 7 8 9 10
Как видите, цикл выводит в консоль все числа от 1 до 10 кроме 5. Когда x
становится равен 5, оставшаяся часть команд не выполняется, а начинается следующая итерация цикла.
Learning with Python, документация 2-го издания
6.1. Множественное присвоение
Как вы, возможно, уже поняли, законно выполнять более одного присвоения та же переменная. Новое присваивание заставляет существующую переменную ссылаться на новое значение (и перестать ссылаться на старое значение).
Брюс = 5 распечатать брюс, Брюс = 7 распечатать Брюс
Вывод этой программы 5 7, потому что в первый раз Брюс напечатано, его значение равно 5, а во второй раз его значение равно 7. Запятая в конце конец первого оператора печати подавляет новую строку после вывода, вот почему оба выхода появляются в одной строке.
Вот как множественное назначение выглядит на диаграмме состояний:
При множественном назначении особенно важно различать операция присваивания и оператор равенства. Поскольку Python использует равные знак (=) для присваивания, заманчиво интерпретировать оператор как a = b как утверждение о равенстве. Нет, это не так!
Во-первых, равенство симметрично, а присваивание — нет. Например, в математика, если а = 7, то 7 = а. Но в Python оператор a = 7 допустимо, а 7 = a — нет.
Кроме того, в математике утверждение о равенстве всегда истинно. Если а = б теперь, тогда a всегда будет равно b. В Python оператор присваивания может сделать две переменные равны, но они не должны оставаться такими:
а = 5 b = a # a и b теперь равны a = 3 # a и b больше не равны
Третья строка изменяет значение a, но не изменяет значение б, так что они уже не равны. (В некоторых языках программирования для присваивания используется символ, например <- или :=, чтобы избежать путаницы.)
6.2. Обновление переменных
Одной из наиболее распространенных форм множественного присвоения является обновление, при котором значение переменной зависит от старого.
х = х + 1
Это означает получение текущего значения x, добавление единицы, а затем обновление x новым значением. ценность.
Если вы попытаетесь обновить несуществующую переменную, вы получите сообщение об ошибке, потому что Python оценивает выражение в правой части оператора присваивания прежде чем он присвоит результирующее значение имени слева:
>>> х = х + 1 Traceback (последний последний вызов): Файл "", строка 1, в NameError: имя «x» не определено
Прежде чем вы сможете обновить переменную, вы должны инициализировать ее , обычно с помощью простое присвоение:
>>> x = 0 >>> х = х + 1 >>>
Обновление переменной путем добавления 1 называется приращением ; вычитание 1 равно называется декрементом .
6.3. Оператор while
Компьютеры часто используются для автоматизации повторяющихся задач. Повторение идентичных или подобные задачи без ошибок — это то, с чем компьютеры справляются хорошо и люди плохо работают.
Повторное выполнение набора операторов называется итерацией . Потому что итерация настолько распространена, что Python предоставляет несколько языковых функций, чтобы сделать ее Полегче. Первая функция, которую мы собираемся рассмотреть, — это оператор while.
Вот функция обратного отсчета, которая демонстрирует использование в то время как оператор:
обратный отсчет (n): при n > 0: напечатать п п = п-1 печатать "Отрыв!"
Вы можете читать инструкцию while почти так, как если бы она была написана на английском языке. Это означает, Пока n больше 0, продолжайте отображать значение n, а затем уменьшая значение n на 1. Когда вы дойдете до 0, отобразите слово Взлетать!
Более формально, вот последовательность выполнения оператора while:
- Вычислить условие, выдав False или True.
- Если условие ложно, выйти из оператора while и продолжить выполнение на следующем операторе.
- Если условие истинно, выполнить каждый из операторов в теле и затем вернитесь к шагу 1.
Тело состоит из всех операторов под заголовком с тем же отступ.
Этот тип потока называется цикл , потому что третий шаг повторяется наверх. Обратите внимание, что если условие ложно в первый раз через цикл, операторы внутри цикла никогда не выполняются.
Тело цикла должно изменить значение одной или нескольких переменных так, чтобы в конце концов условие становится ложным, и цикл завершается. В противном случае цикл будет повторяться вечно, что называется бесконечным циклом . Бесконечный источником развлечения для специалистов по информатике является наблюдение, что указания по шампуню, намыльте, промойте, повторите, это бесконечный цикл.
В случае обратного отсчета мы можем доказать, что цикл завершается, потому что мы знаем, что значение n конечно, и мы можем видеть, что значение n становится меньше с каждым разом в цикле, поэтому в конце концов мы должны добраться до 0. В другие случаи, это не так легко сказать. Посмотрите на следующую функцию, определено для всех положительных целых чисел n:
def sequence(n): в то время как n != 1: напечатать п, если n % 2 == 0: # n четно п = п / 2 иначе: # n нечетно п = п * 3 + 1
Условие для этого цикла n != 1, поэтому цикл будет продолжаться до тех пор, пока n равно 1, что сделает условие ложным.
Каждый раз в цикле программа выводит значение n, а затем проверяет, четное оно или нечетное. Если оно четное, значение n делится на 2. Если оно нечетное, значение заменяется на n * 3 + 1. Например, если начальное значение (аргумент, переданный в sequence) равно 3, в результате последовательность 3, 10, 5, 16, 8, 4, 2, 1.
Поскольку n иногда увеличивается, а иногда уменьшается, нет очевидного доказательство того, что n когда-либо достигнет 1 или что программа завершится. Для некоторых конкретных значений n, мы можем доказать терминацию. Например, если начальное значение является степенью двойки, тогда значение n будет четным каждый время в цикле, пока не достигнет 1. Предыдущий пример заканчивается таким последовательность, начиная с 16.
Помимо конкретных значений, интересен вопрос, можем ли мы доказать, что эта программа завершает на все значения n. Пока никому не удалось чтобы доказать это или опровергнуть это!
6.4. Отслеживание программы
Чтобы писать эффективные компьютерные программы, программист должен развить способность к отслеживать выполнение компьютерной программы. Трассировка включает в себя становление компьютер и следуя за потоком выполнения через пример запуска программы, запись состояния всех переменных и любых выходных данных, которые программа генерирует после каждая инструкция выполняется.
Чтобы понять этот процесс, давайте проследим вызов sequence(3) из предыдущий раздел. В начале трассировки у нас есть локальная переменная n (параметр) с начальным значением 3. Поскольку 3 не равно 1, пока выполняется тело цикла. Выводится 3 и оценивается 3 % 2 == 0. Поскольку он оценивается как False, выполняется ветвь else и 3 * 3 + 1 оценивается и присваивается n.
Чтобы следить за всем этим, пока вы вручную трассируете программу, создайте заголовок столбца на лист бумаги для каждой переменной, созданной во время работы программы, и еще один для вывода. Наша трассировка пока будет выглядеть примерно так:
н выход -- ------ 3 3 10
Поскольку 10 != 1 оценивается как True, снова выполняется тело цикла, и напечатано 10. 10 % 2 == 0 истинно, поэтому ветвь if выполняется, и n становится равным 5. К концу трассировки мы имеем:
n выходных данных -- ------ 3 3 10 10 5 5 16 16 8 8 4 4 2 2 1
Трассировка может быть немного утомительной и подверженной ошибкам (вот почему мы заставляем компьютеры выполнять это в первую очередь!), но это важный навык для программиста иметь. Из этой трассировки мы можем многое узнать о том, как работает наш код. Мы можно заметить, что как только n станет степенью двойки, например, программа потребуется журнал 2 (n) выполнение тела цикла для завершения. Мы можем также обратите внимание, что последняя 1 не будет напечатана в качестве вывода.
6.5. Подсчет цифр
Следующая функция подсчитывает количество десятичных цифр в положительном целое число, выраженное в десятичном формате:
def num_digits(n): количество = 0 в то время как н: количество = количество + 1 п = п / 10 количество возвратов
Вызов num_digits(710) вернет 3. Проследите выполнение этого вызов функции, чтобы убедиться, что она работает.
Эта функция демонстрирует другую схему вычислений, называемую счетчиком . Переменная count инициализируется 0, а затем увеличивается каждый раз, когда выполняется тело цикла. Когда цикл завершается, count содержит результат – общее количество выполнений тела цикла, которое совпадает с количество цифр.
Если бы мы хотели подсчитывать только цифры, равные 0 или 5, добавление условного перед увеличением счетчика добьется цели:
def num_zero_and_five_digits(n): количество = 0 в то время как н: цифра = п % 10 если цифра == 0 или цифра == 5: количество = количество + 1 п = п / 10 количество возвратов
Подтвердите, что num_zero_and_five_digits(1055030250) возвращает 7.
6.7. Таблицы
Циклы хорошо подходят для создания табличных данных. До компьютеры были легко доступны, люди должны были вычислять логарифмы, синусы и косинусы и другие математические функции вручную. Чтобы сделать это проще, книги по математике содержали длинные таблицы со значениями этих функций. Создание таблиц было медленным и скучным, и они, как правило, были полны ошибок.
Когда на сцене появились компьютеры, одной из первых реакций было: «Это большой! Мы можем использовать компьютеры для создания таблиц, так что не будет ошибки. Это оказалось правдой (в основном), но недальновидно. Вскоре после этого, компьютеры и калькуляторы были настолько распространены, что таблицы устарели.
Ну, почти. Для некоторых операций компьютеры используют таблицы значений, чтобы получить приблизительный ответ, а затем выполнить вычисления, чтобы улучшить приближение. В некоторых случаях в базовых таблицах были ошибки, наиболее известные из которых в таблице Intel Pentium используется для выполнения деления с плавающей запятой.
Хотя таблица журнала уже не так полезна, как когда-то, она по-прежнему полезна. пример итерации. Следующая программа выводит последовательность значений в левый столбец и 2 в степени этого значения в правом столбце:
x = 1 пока х < 13: напечатать х, '\t', 2**х х += 1
Строка '\t' представляет собой символ табуляции . Символ обратной косой черты в '\t' указывает на начало управляющей последовательности . Escape-последовательности используются для представления невидимых символов, таких как табуляция и новая строка. Последовательность \n представляет новая строка .
Управляющая последовательность может появляться в любом месте строки; в этом примере вкладка escape-последовательность — это единственное, что есть в строке. Как вы думаете, вы представляете обратная косая черта в строке?
Когда символы и строки отображаются на экране, невидимый маркер называемый курсор отслеживает, куда пойдет следующий символ. После оператор печати, курсор обычно переходит в начало следующего линия.
Символ табуляции перемещает курсор вправо до тех пор, пока он не достигнет одного из табуляция останавливается. Вкладки полезны для выравнивания столбцов текста, как в выводе. предыдущей программы:
1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024 11 2048 12 4096
Из-за символов табуляции между столбцами положение второго столбца не зависит от количества цифр в первом столбце.
6.8. Двумерные таблицы
Двумерная таблица — это таблица, в которой вы считываете значение на пересечении строки и столбца. Таблица умножения является хорошим примером. Скажем, вы хотите напечатать таблицу умножения для значений от 1 до 6.
Хороший способ начать — написать цикл, который печатает числа, кратные 2, все на одна строка:
я = 1 пока я <= 6: напечатать 2 * я, ' ', я += 1 Распечатать
Первая строка инициализирует переменную с именем i, которая действует как счетчик или переменная цикла . По мере выполнения цикла значение i увеличивается с 1 до 6. Когда i равно 7, цикл завершается. Каждый раз через цикл он отображает значение 2 * i, за которым следуют три пробела.
Опять же, запятая в операторе печати подавляет новую строку. После цикл завершается, второй оператор печати начинает новую строку.
Вывод программы:
2 4 6 8 10 12
Пока все хорошо. Следующий шаг — инкапсулировать и обобщить .
6.9. Инкапсуляция и обобщение
Инкапсуляция — это процесс помещения фрагмента кода в функцию, позволяя вам воспользоваться всеми преимуществами функций. Ты вы уже видели два примера инкапсуляции: print_parity в главе 4; и is_divisible в главе 5.
Обобщение означает взятие чего-то конкретного, например печать кратных из 2, и сделать его более общим, например, распечатать кратные любому целое число.
Эта функция инкапсулирует предыдущий цикл и обобщает его для печати кратно n:
def print_multiples(n): я = 1 пока я <= 6: выведите n * i, '\t', я += 1 Распечатать
Для инкапсуляции все, что нам нужно было сделать, это добавить первую строку, которая объявляет имя функции и список параметров. Обобщая, все, что нам нужно было сделать было заменить значение 2 параметром n.
Если мы вызовем эту функцию с аргументом 2, мы получим тот же результат, что и раньше. С аргументом 3 вывод:
3 6 9 12 15 18
С аргументом 4 вывод:
4 8 12 16 20 24
Теперь вы, наверное, догадались, как распечатать таблицу умножения — по многократный вызов print_multiples с разными аргументами. На самом деле мы можно использовать другой цикл:
i = 1 пока я <= 6: print_multiples (я) я += 1
Обратите внимание, насколько этот цикл похож на цикл внутри print_multiples. Все мы сделал, заменил оператор печати вызовом функции.
Результатом работы этой программы является таблица умножения:
1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 5 10 15 20 25 30 6 12 18 24 30 36
6.10. Подробнее об инкапсуляции
Чтобы еще раз продемонстрировать инкапсуляцию, возьмем код из последнего раздела. и заверните его в функцию:
определение print_mult_table(): я = 1 пока я <= 6: print_multiples (я) я += 1
Этот процесс является общим планом разработки . Мы разрабатываем код, написав строки кода вне какой-либо функции или ввода их в интерпретатор. Когда мы получим код работает, мы извлекаем его и заворачиваем в функцию.
Этот план развития особенно полезен, если вы не знаете, как разделить программу в функции, когда вы начинаете писать. Этот подход позволяет вам дизайн, как вы идете вперед.
6.11. Локальные переменные
Вам может быть интересно, как мы можем использовать одну и ту же переменную i в обоих print_multiples и print_mult_table. Не вызывает ли это проблем, когда одна из функций изменяет значение переменной?
Нет, потому что i в print_multiples и i в print_mult_table - это , а не одна и та же переменная.
Переменные, созданные внутри определения функции, являются локальными; вы не можете получить доступ к локальная переменная из-за пределов своей домашней функции. Это означает, что вы можете иметь несколько переменных с одним и тем же именем, если они не находятся в одном и том же функция.
Диаграмма стека для этой программы показывает, что две переменные с именем i не одна и та же переменная. Они могут относиться к разным значениям, и изменение одного не влияет на другое.
Значение i в print_mult_table изменяется от 1 до 6. На диаграмме это оказывается 3. В следующий раз через цикл это будет 4. Каждый раз через цикл, print_mult_table вызывает print_multiples с текущим значением я в качестве аргумента. Это значение присваивается параметру n.
Внутри print_multiples значение i изменяется от 1 до 6. В диаграмме, это 2. Изменение этой переменной не влияет на значение из i в print_mult_table.
Общепринято и совершенно законно иметь разные локальные переменные с то же имя. В частности, такие имена, как i и j, часто используются как переменные цикла. Если вы избегаете их использования в одной функции только потому, что использовали их в другом месте, вы, вероятно, затрудните чтение программы.
6.12. Больше обобщений
В качестве еще одного примера обобщения представьте, что вам нужна программа, которая напечатать таблицу умножения любого размера, а не только таблицу шесть на шесть. Ты можно добавить параметр в print_mult_table:
def print_mult_table(high): я = 1 в то время как я <= высокий: print_multiples (я) я += 1
Мы заменили значение 6 параметром high. Если мы позвоним print_mult_table с аргументом 7 выводит:
1 2 3 4 5 6 2 4 6 8 10 12 3 6 912 15 18 4 8 12 16 20 24 5 10 15 20 25 30 6 12 18 24 30 36 7 14 21 28 35 42
Это нормально, за исключением того, что мы, вероятно, хотим, чтобы таблица была квадратной — с одинаковое количество строк и столбцов. Для этого добавим еще один параметр в print_multiples, чтобы указать, сколько столбцов должно быть в таблице.
Просто чтобы не раздражать, мы называем этот параметр высоким, демонстрируя, что разные функции могут иметь параметры с одинаковыми именами (так же, как локальные переменные). Вот и вся программа:
по умолчанию print_multiples(n, high): я = 1 в то время как я <= высокий: выведите n*i, '\t', я += 1 Распечатать def print_mult_table (высокий): я = 1 в то время как я <= высокий: print_multiples (я, высокий) я += 1
Обратите внимание: когда мы добавили новый параметр, нам пришлось изменить первую строку функцию (заголовок функции), а также пришлось изменить место, где функция вызывается в print_mult_table.
Как и ожидалось, эта программа создает квадратную таблицу семь на семь:
1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 6 9 12 15 18 21 4 8 12 16 20 24 28 5 10 15 20 25 30 35 6 12 18 24 30 36 42 7 14 21 28 35 42 49
Когда вы соответствующим образом обобщаете функцию, вы часто получаете программу с возможности, которые вы не планировали. Например, вы можете заметить, что поскольку ab = ba все записи в таблице появляются дважды. Вы можете сэкономить чернила, распечатав только половина стола. Для этого вам нужно всего лишь изменить одну строку print_mult_table. Изменить
print_multiples(i, высокий)от
до
print_multiples(i, i)
и вы получите:
1 2 4 3 6 9 4 8 12 16 5 10 15 20 25 6 12 18 24 30 36 7 14 21 28 35 42 49
6.13. Функции
Несколько раз мы упоминали обо всем, для чего нужны функции. По Теперь вам может быть интересно, что именно это за вещи. Вот некоторые из их:
- Присвоение имени последовательности операторов упрощает чтение программы. и отлаживать.
- Разделение длинной программы на функции позволяет разделить части программы, отлаживать их по отдельности, а затем составлять из них единое целое.
- Функции облегчают использование итераций.
- Хорошо продуманные функции часто полезны для многих программ. Как только вы напишете и отладить один, вы можете использовать его повторно.
6.14. Метод Ньютона
Циклы часто используются в программах, которые вычисляют численные результаты, начиная с приблизительным ответом и итеративным его улучшением.
Например, одним из способов вычисления квадратных корней является метод Ньютона. Предполагать что вы хотите знать квадратный корень из n. Если начать почти с любого приближение, вы можете вычислить лучшее приближение с помощью следующего формула:
лучше = (приблизительно + n/приблизительно)/2
Повторно применяя эту формулу до тех пор, пока лучшее приближение не будет равно предыдущий, мы можем написать функцию для вычисления квадратного корня:
def sqrt(n): приблизительно = n/2,0 лучше = (приблизительно + n/приблизительно)/2,0 а лучше != примерно: приблизительно = лучше лучше = (приблизительно + n/приблизительно)/2,0 вернуться примерно
Попробуйте вызвать эту функцию с 25 в качестве аргумента, чтобы убедиться, что она возвращает 5. 0.
6.15. Алгоритмы
Метод Ньютона является примером алгоритма : это механический процесс для решения категории задач (в данном случае для вычисления квадратных корней).
Определить алгоритм непросто. Это может помочь начать с чего-то это не алгоритм. Когда вы научились умножать однозначные числа, Вы, наверное, выучили таблицу умножения. По сути, вы запомнили 100 конкретные решения. Такое знание не является алгоритмическим.
Но если вы были ленивы, вы, вероятно, обманули, изучив несколько трюков. За например, чтобы найти произведение n и 9, вы можете написать n - 1 как первую цифру а 10 - n как вторая цифра. Этот трюк является общим решением для умножение любого однозначного числа на 9. Это алгоритм!
Точно так же методы сложения с переносом, вычитания, которые вы изучили с заимствованием и делением в длину — все это алгоритмы. Один из особенностью алгоритмов является то, что они не требуют никакого интеллекта для выполнять. Это механические процессы, в которых каждый шаг вытекает из последние по простому набору правил.
По нашему мнению, стыдно, что люди так много времени проводят в школе научиться выполнять алгоритмы, которые буквально не требуют интеллекта.
С другой стороны, процесс разработки алгоритмов интересен, интеллектуально сложной и центральной частью того, что мы называем программированием.
Некоторые вещи, которые люди делают естественно, без затруднений или сознательно мысли труднее всего выразить алгоритмически. Понимание естественного язык является хорошим примером. Мы все это делаем, но пока никому не удалось объяснить как мы это делаем, по крайней мере не в виде алгоритма.
6.16. Глоссарий
- алгоритм
- Пошаговый процесс решения категории проблем.
- корпус
- Операторы внутри цикла.
- счетчик
- Переменная, используемая для подсчета чего-либо, обычно инициализируется нулем и увеличивается в теле цикла.
- курсор
- Невидимый маркер, который отслеживает, где будет следующий символ. быть напечатаны.
- уменьшение
- Уменьшить на 1.
- план развития
- Процесс разработки программы. В этой главе мы продемонстрировали стиль разработки, основанный на разработке кода для выполнения простых, конкретных вещи, а затем инкапсулировать и обобщать.
- инкапсулировать
- Чтобы разделить большую сложную программу на компоненты (например, функции) и изолировать компоненты друг от друга (используя локальные переменные, для пример).
- управляющая последовательность
- Управляющий символ \, за которым следует один или несколько печатных символов. используется для обозначения непечатаемого символа.
- обобщить
- Чтобы заменить что-то излишне конкретное (например, постоянное значение) с чем-то подходящим общим (например, с переменной или параметром). Обобщение делает код более универсальным, более вероятным для повторного использования и иногда даже проще написать.
- приращение
- Как существительное, так и глагол, приращение означает увеличение на 1.
- бесконечный цикл
- Цикл, в котором условие завершения никогда не выполняется.
- инициализация (переменной)
- Инициализировать переменную означает присвоить ей начальное значение, обычно в контекст многократного присвоения. Поскольку в Python переменных не существует пока им не будут присвоены значения, они инициализируются, когда они созданный. В других языках программирования это не так, и переменные могут быть созданы без инициализации, и в этом случае они либо по умолчанию, либо мусор значения.
- итерация
- Повторное выполнение набора операторов программирования.
- петля
- Оператор или группа операторов, которые выполняются многократно до тех пор, пока условие завершения выполнено.
- переменная цикла
- Переменная, используемая как часть условия завершения цикла.
- множественное присвоение
- Выполнение более одного присвоения одной и той же переменной во время выполнение программы.
- новая строка
- Специальный символ, который заставляет курсор перемещаться в начало следующая строка.
- вкладка
- Специальный символ, который заставляет курсор перемещаться на следующую позицию табуляции на текущей строке.
- трассировка
- Следить за ходом выполнения программы вручную, записывая изменение состояния переменных и любого произведенного вывода.
6.17. Упражнения
Напишите одну строку, которая:
производит это выход.
Добавьте оператор печати в функцию sqrt, определенную в разделе 6.14, которая печатает лучше каждый раз, когда он вычисляется. Назовите свой измененный функцию с 25 в качестве аргумента и запишите результаты.
Отследить выполнение последней версии print_mult_table и рисунка как это работает.
Напишите функцию print_triangular_numbers(n), которая выводит первое n треугольных чисел. Вызов print_triangular_numbers(5) произвести следующий вывод:
1 1 2 3 3 6 4 10 5 15
(подсказка : используйте веб-поиск, чтобы узнать, что такое треугольное число. )
Откройте файл с именем ch06.py и добавьте следующее:
, если __name__ == '__main__': импортировать доктест doctest.testmod()
Напишите функцию is_prime, которая принимает один целочисленный аргумент. и возвращает True, если аргументом является простое число и False в противном случае. Добавляйте doctests в свою функцию по мере ее разработки.
Что вернет num_digits(0)? Измените его, чтобы вернуть 1 для этого кейс. Почему вызов num_digits(-24) приводит к бесконечному циклу (подсказка : -1/10 равно -1 )? Измените num_digits, чтобы он работал корректно с любым целочисленным значением. Добавьте следующее в ch06.py файл, который вы создали в предыдущем упражнении:
по определению num_digits(n): """ >>> число_цифр (12345) 5 >>> число_цифр (0) 1 >>> число_цифр (-12345) 5 """
Добавьте тело функции в num_digits и подтвердите, что оно проходит доктесты.
Добавьте в ch06.py следующее:
по определению num_even_digits(n): """ >>> число_четных_цифр (123456) 3 >>> число_четных_цифр (2468) 4 >>> число_четных_цифр (1357) 0 >>> число_четных_цифр (2) 1 >>> число_четных_цифр (20) 2 """
Напишите тело для num_even_digits, чтобы оно работало должным образом.
Добавьте в ch06.py следующее:
по определению print_digits(n): """ >>> print_digits(13789) 9 8 7 3 1 >>> print_digits(39874613) 3 1 6 4 7 8 9 3 >>> print_digits(213141) 1 4 1 3 1 2 """
Напишите тело для print_digits, чтобы оно прошло заданные doctests.
Напишите функцию sum_of_squares_of_digits, которая вычисляет сумму квадратов цифр переданного ему целого числа. Например, sum_of_squares_of_digits(987) должен вернуть 194, так как 9**2 + 8**2 + 7**2 == 81 + 64 + 49 == 194.
по определению sum_of_squares_of_digits(n): """ >>> сумма_квадратов_цифр(1) 1 >>> сумма_квадратов_цифр(9) 81 >>> сумма_квадратов_цифр (11) 2 >>> сумма_квадратов_цифр (121) 6 >>> сумма_квадратов_цифр (987) 194 """
Проверьте свое решение на соответствие doctests выше.
while loop - cppreference.com
Язык C++
Операторы
Выполняет оператор повторно, пока значение условия не станет ложным. Проверка проводится перед каждой итерацией.
|
[править] Синтаксис
attr (необязательно) while ( условие ) оператор | |||||||||
атрибут | - | (начиная с C++11) любое количество атрибутов |
состояние | - | любое выражение, контекстуально преобразуемое в логическое значение, или объявление одной переменной с инициализатором типа "скобка или равенство". Это выражение вычисляется перед каждой итерацией, и если оно дает false, цикл завершается. Если это объявление, инициализатор оценивается перед каждой итерацией, и если значение объявленной переменной становится ложным, цикл завершается. |
заявление | - | любой оператор, обычно составной оператор, являющийся телом цикла |
[править] Объяснение
Независимо от того, является ли оператор составным оператором, он всегда вводит область действия блока. Объявленные в нем переменные видны только в теле цикла, другими словами,
пока (--x >= 0) инт я; // я выхожу за рамки
то же, что и
пока (--x >= 0) { инт я; } // я выхожу за рамки
Если условие является объявлением, таким как T t = x, объявленная переменная находится в области видимости только в теле цикла и уничтожается и создается заново на каждой итерации, другими словами, такой цикл while эквивалентен
этикетка: { // начало области действия условия Т т = х; Если T) { утверждение перейти к метке; // вызывает деструктор t } }
Если выполнение цикла необходимо прервать в какой-то момент, можно использовать оператор break в качестве завершающего оператора.