Книга Изучаем Python
Скачать 4.68 Mb.
|
УПРАЖНЕНИЯ 7-1 . Прокат машин: напишите программу, которая спрашивает у пользователя, какую ма- шину он хотел бы взять напрокат . Выведите сообщение с введенными данными (например, “Let me see if I can find you a Subaru”) . 7-2 . Заказ стола: напишите программу, которая спрашивает у пользователя, на сколько мест он хочет забронировать стол в ресторане . Если введенное число больше 8, выведите сообщение о том, что пользователю придется подождать . В противном случае сообщите, что стол готов . 7-3 . Числа, кратные 10: запросите у пользователя число и сообщите, кратно оно 10 или нет . Циклы while Цикл for получает коллекцию элементов и выполняет блок кода по одному разу для каждого элемента в коллекции. В отличие от него, цикл while продолжает вы- полняться, пока остается истинным некоторое условие. Цикл while в действии Цикл while может использоваться для перебора числовой последовательности. Например, следующий цикл считает от 1 до 5: counting.py current_number = 1 while current_number <= 5: print(current_number) current_number += 1 В первой строке отсчет начинается с 1, для чего current_number присваивается значение 1. Далее запускается цикл while , который продолжает работать, пока значение current_number остается меньшим или равным 5. Код в цикле выводит значение current_number и увеличивает его на 1 командой current_number += 1 (Оператор += является сокращенной формой записи для current_number = current_number + 1 .) Цикл повторяется, пока условие current_number <= 5 остается истинным. Так как 1 меньше 5, Python выводит 1, а затем увеличивает значение на 1, отчего current_ number становится равным 2. Так как 2 меньше 5, Python выводит 2 и снова при- Циклы while 125 бавляет 1 и т. д. Как только значение current_number превысит 5, цикл останавли- вается, а программа завершается: 1 2 3 4 5 Очень многие повседневные программы содержат циклы while . Например, представьте компьютерную игру: цикл while выполняется, пока игра про- должается, и завершается, как только игрок захочет остановить игру. Вряд ли кого-нибудь обрадует, если программа завершает работу преждевременно или продолжает работать, когда ей приказали остановиться, так что циклы while весьма полезны. Пользователь решает прервать работу программы Программа parrot .py может выполняться, пока пользователь не захочет остановить ее, — для этого бульшая часть кода заключается в цикл while . В программе опре- деляется признак завершения, и программа работает, пока пользователь не введет нужное значение: parrot.py prompt = "\nTell me something, and I will repeat it back to you:" prompt += "\nEnter 'quit' to end the program. " message = "" while message != 'quit': message = input(prompt) print(message) В точке определяется сообщение, которое объясняет, что у пользователя есть два варианта: ввести сообщение или ввести признак завершения (в данном случае это строка 'quit' ). Затем переменной message присваивается значение, введен- ное пользователем. В программе переменная message инициализируется пустой строкой "" , чтобы значение проверялось без ошибок при первом выполнении строки while . Когда программа только запускается и выполнение достигает ко- манды while , значение message необходимо сравнить с 'quit' , но пользователь еще не вводил никакие данные. Если у Python нет данных для сравнения, продолжение выполнения становится невозможным. Чтобы решить эту проблему, необходимо предоставить message исходное значение. И хотя это всего лишь пустая строка, для Python такое значение выглядит вполне осмысленно; программа сможет выполнить сравнение, на котором основана работа цикла while . Цикл while выполняется, пока значение message не равно 'quit' При первом выполнении цикла message содержит пустую строку, и Python входит в цикл. При выполнении команды message = input(prompt) Python отображает подсказку и ожидает, пока пользователь введет данные. Эти данные сохраняются в message и выводятся командой print ; после этого Python снова проверяет усло- вие команды while . Пока пользователь не введет слово 'quit' , приглашение будет 126 Глава 7 • Ввод данных и циклы while выводиться снова и снова, а Python будет ожидать новых данных. При вводе слова 'quit' Python перестает выполнять цикл while , а программа завершается: Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello everyone! Hello everyone! Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello again. Hello again. Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. quit quit Программа работает неплохо, если не считать того, что она выводит слово 'quit' , словно оно является обычным сообщением. Простая проверка if решает про- блему: prompt = "\nTell me something, and I will repeat it back to you:" prompt += "\nEnter 'quit' to end the program. " message = "" while message != 'quit': message = input(prompt) if message != 'quit': print(message) Теперь программа проводит проверку перед выводом сообщения и выводит со- общение только в том случае, если оно не совпадает с признаком завершения: Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello everyone! Hello everyone! Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello again. Hello again. Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. quit Флаги В предыдущем примере программа выполняла некоторые операции, пока заданное условие оставалось истинным. А что если вы пишете более сложную программу, выполнение которой может прерываться по нескольким разным условиям? Например, компьютерная игра может завершаться по разным причинам: у игро- ка кончились все «жизни»; прошло отведенное время; все города, которые он должен был защищать, были уничтожены и т. д. Игра должна завершаться при выполнении любого из этих условий. Попытки проверять все возможные условия в одной команде while быстро усложняются и становятся слишком громоздкими. Циклы while 127 Если программа должна выполняться только при истинности нескольких условий, определите одну переменную-флаг. Эта переменная сообщает, должна ли програм- ма выполняться далее. Программу можно написать так, чтобы она продолжала выполнение, если флаг находится в состоянии True , и завершалась, если любое из нескольких событий перевело флаг в состояние False . В результате в команде while достаточно проверить всего одно условие: находится ли флаг в состоянии True . Все остальные проверки (которые должны определить, произошло ли собы- тие, переводящее флаг в состояние False ) удобно организуются в остальном коде. Добавим флаг в программу parrot .py из предыдущего раздела. Этот флаг, который мы назовем active (хотя переменная может называться как угодно), управляет тем, должно ли продолжаться выполнение программы: prompt = "\nTell me something, and I will repeat it back to you:" prompt += "\nEnter 'quit' to end the program. " active = True while active: message = input(prompt) if message == 'quit': active = False else: print(message) В точке переменной active присваивается True , чтобы программа начинала работу в активном состоянии. Это присваивание упрощает команду while , потому что в самой команде while никакие сравнения не выполняются; вся логика реали- зуется в других частях программы. Пока переменная active остается равной True , цикл выполняется. В команде if внутри цикла while значение message проверяется после того, как пользователь введет данные. Если пользователь ввел строку 'quit' , флаг active переходит в состояние False , а цикл while останавливается. Если пользователь ввел любой текст, кроме 'quit' , то введенные им данные выводятся как сообщение. Результаты работы этой программы ничем не отличаются от предыдущего приме- ра, в котором условная проверка выполняется прямо в команде while . Но теперь в программе имеется флаг, указывающий, находится ли она в активном состоянии, и вы сможете легко добавить новые проверки (в форме команд elif ) для событий, с которыми переменная active может перейти в состояние False . Это может быть удобно в сложных программах — например, в компьютерных играх с многочислен- ными событиями, каждое из которых может привести к завершению программы. Когда по любому из этих событий флаг active переходит в состояние False , основ- ной игровой цикл прервется, выводится сообщение о завершении игры, и у игрока появляется возможность сыграть еще раз. Команда break и выход из цикла Чтобы немедленно прервать цикл while без выполнения оставшегося кода в цикле независимо от состояния условия, используйте команду break . Команда break 128 Глава 7 • Ввод данных и циклы while управляет ходом выполнения программы; она позволит вам управлять тем, какая часть кода выполняется, а какая нет. Рассмотрим пример — программу, которая спрашивает у пользователя, в каких го- родах он бывал. Чтобы прервать цикл while , программа выполняет команду break , как только пользователь введет значение 'quit' : cities.py prompt = "\nPlease enter the name of a city you have visited:" prompt += "\n(Enter 'quit' when you are finished.) " while True: city = input(prompt) if city == 'quit': break else: print("I'd love to go to " + city.title() + "!") Цикл, который начинается с while True , будет выполняться бесконечно — если только в нем не будет выполнена команда break . Цикл в программе продолжает запрашивать у пользователя названия городов, пока пользователь не введет строку 'quit' . При вводе строки 'quit' выполняется команда break , по которой Python выходит из цикла: Please enter the name of a city you have visited: (Enter 'quit' when you are finished.) New York I'd love to go to New York! Please enter the name of a city you have visited: (Enter 'quit' when you are finished.) San Francisco I'd love to go to San Francisco! Please enter the name of a city you have visited: (Enter 'quit' when you are finished.) quit ПРИМЕЧАНИЕ Команда break может использоваться в любых циклах Python . Например, ее можно вклю- чить в цикл for для перебора элементов словаря . Команда continue и продолжение цикла Вместо того чтобы полностью прерывать выполнение цикла без выполнения остав- шейся части кода, вы можете воспользоваться командой continue для возвращения к началу цикла и проверке условия. Например, возьмем цикл, который считает от 1 до 10, но выводит только нечетные числа в этом диапазоне: counting.py current_number = 0 while current_number < 10: current_number += 1 if current_number % 2 == 0: Циклы while 129 continue print(current_number) Сначала переменной current_number присваивается 0. Так как значение меньше 10, Python входит в цикл while . При входе в цикл счетчик увеличивается на 1 в точ- ке , поэтому current_number принимает значение 1. Затем команда if проверяет остаток от деления current_number на 2. Если остаток равен 0 (это означает, что current_number делится на 2), команда continue приказывает Python проигно- рировать оставшийся код цикла и вернуться к началу. Если счетчик не делится на 2, то оставшаяся часть цикла выполняется, и Python выводит текущее значение счетчика: 1 3 5 7 9 Предотвращение зацикливания У каждого цикла while должна быть предусмотрена возможность завершения, что- бы цикл не выполнялся бесконечно. Например, следующий цикл считает от 1 до 5: counting.py x = 1 while x <= 5: print(x) x += 1 Но если случайно пропустить строку x += 1 (см. далее), то цикл будет выполняться бесконечно: # Бесконечный цикл! x = 1 while x <= 5: print(x) Теперь переменной x присваивается начальное значение 1, но это значение никог- да не изменяется в программе. В результате проверка условия x <= 5 всегда дает результат True , и цикл while выводит бесконечную серию единиц: 1 1 1 1 … Любой программист время от времени пишет бесконечный цикл, особенно если в программе используются неочевидные условия завершения. Если ваша про- грамма зациклилась, нажмите Ctrl+C или просто закройте терминальное окно с выводом программы. 130 Глава 7 • Ввод данных и циклы while Чтобы избежать зацикливания, тщательно проверьте каждый цикл while и убеди- тесь в том, что цикл прерывается именно тогда, когда предполагается. Если про- грамма должна завершаться при вводе некоторого значения, запустите программу и введите это значение. Если программа не завершилась, проанализируйте обра- ботку значения, которое должно приводить к выходу из цикла. Проверьте, чтобы хотя бы одна часть программы могла привести к тому, что условие цикла станет равно False или будет выполнена команда break ПРИМЕЧАНИЕ В некоторых редакторах — например, в Sublime Text — используется встроенное окно вывода . Оно может усложнить прерывание бесконечных циклов; возможно, для выхода из цикла придется за- крыть редактор . УПРАЖНЕНИЯ 7-4 . Дополнения для пиццы: напишите цикл, который предлагает пользователю вводить дополнения для пиццы до тех пор, пока не будет введено значение 'quit’ . При вводе каждо- го дополнения выведите сообщение о том, что это дополнение включено в заказ . 7-5 . Билеты в кино: кинотеатр установил несколько вариантов цены на билеты в зависимо- сти от возраста посетителя . Для посетителей младше 3 лет билет бесплатный; в возрасте от 3 до 12 билет стоит $10; наконец, если возраст посетителя больше 12, билет стоит $15 . Напишите цикл, который предлагает пользователю ввести возраст и выводит цену билета . 7-6 . Три выхода: напишите альтернативную версию упражнения 7-4 или упражнения 7-5, в которой каждый пункт следующего списка встречается хотя бы один раз . • Завершение цикла по проверке условия в команде while . • Управление продолжительностью выполнения цикла в зависимости от переменной active . • Выход из цикла по команде break, если пользователь вводит значение ‘quit’ . 7-7 . Бесконечный цикл: напишите цикл, который никогда не завершается, и выполните его . (Чтобы выйти из цикла, нажмите Ctrl+C или закройте окно с выводом .) Использование цикла while со списками и словарями До настоящего момента мы работали только с одним фрагментом информации, полученной от пользователя. Мы получали ввод пользователя, а затем выводили ответ на него. При следующем проходе цикла while программа получала новое входное значение и реагировала на него. Но, чтобы работать с несколькими фрагментами информации, необходимо использовать в циклах while списки и словари. Цикл for хорошо подходит для перебора списков, но, скорее всего, список не дол- жен изменяться в цикле, потому что у Python возникнут проблемы с отслежива- нием элементов. Чтобы изменять список в процессе обработки, используйте цикл while . Использование циклов while со списками и словарями позволяет собирать, хранить и упорядочивать большие объемы данных для последующего анализа и обработки. Возьмем список недавно зарегистрированных, но еще не проверенных пользова- телей сайта. Как переместить пользователей после проверки в отдельный список Использование цикла while со списками и словарями 131 проверенных пользователей? Одно из возможных решений: используем цикл while для извлечения пользователей из списка непроверенных, проверяем их и включаем в отдельный список проверенных пользователей. Код может выглядеть так: confirmed_users.py # Начинаем с двух списков: пользователей для проверки # и пустого списка для хранения проверенных пользователей. unconfirmed_users = ['alice', 'brian', 'candace'] confirmed_users = [] # Проверяем каждого пользователя, пока остаются непроверенные # пользователи. Каждый пользователь, прошедший проверку, # перемещается в список проверенных. while unconfirmed_users: current_user = unconfirmed_users.pop() print("Verifying user: " + current_user.title()) confirmed_users.append(current_user) # Вывод всех проверенных пользователей. print("\nThe following users have been confirmed:") for confirmed_user in confirmed_users: print(confirmed_user.title()) Работа программы начинается с двух списков: непроверенных пользователей и пустого списка для проверенных пользователей. Цикл while в точке выпол- няется, пока в списке unconfirmed_users остаются элементы. Внутри этого списка функция pop() в точке извлекает очередного непроверенного пользователя с конца списка unconfirmed_users . В данном примере список unconfirmed_users завершается пользователем Candace ; это имя первым извлекается из списка, со- храняется в current_user и добавляется в список confirmed_users в точке . Далее следуют пользователи Brian и Alice Программа моделирует проверку каждого пользователя выводом сообщения, после чего переносит пользователя в список проверенных. По мере сокращения списка непроверенных пользователей список проверенных пользователей растет. Когда в списке непроверенных пользователей не остается ни одного элемента, цикл оста- навливается, и выводится список проверенных пользователей: Verifying user: Candace Verifying user: Brian Verifying user: Alice The following users have been confirmed: Candace Brian Alice Удаление всех вхождений конкретного значения из списка В главе 3 функция remove() использовалась для удаления конкретного значения из списка. Функция remove() работала, потому что интересующее нас значение 132 Глава 7 • Ввод данных и циклы while встречалось в списке только один раз. Но что если вы захотите удалить все вхож- дения значения из списка? Допустим, имеется список pets , в котором значение 'cat' встречается многократно. Чтобы удалить все экземпляры этого значения, можно выполнять цикл while до тех пор, пока в списке не останется ни одного экземпляра 'cat' : pets.py pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat'] print(pets) while 'cat' in pets: pets.remove('cat') print(pets) Программа начинает со списка, содержащего множественные экземпляры 'cat' После вывода списка Python входит в цикл while , потому что значение 'cat' при- сутствует в списке хотя бы в одном экземпляре. После входа цикл Python удаляет первое вхождение 'cat' , возвращается к строке while , а затем обнаруживает, что экземпляры 'cat' все еще присутствуют в списке, и проходит цикл заново. Вхож- дения 'cat' удаляются до тех пор, пока не окажется, что в списке значений 'cat' не осталось; в этот момент Python завершает цикл и выводит список заново: ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat'] ['dog', 'dog', 'goldfish', 'rabbit'] Заполнение словаря данными, введенными пользователем При каждом проходе цикла while ваша программа может запрашивать любое необходимое количество данных. Напишем программу, которая при каждом про- ходе цикла запрашивает имя участника и его ответ. Собранные данные будут со- храняться в словаре, потому что каждый ответ должен быть связан с конкретным пользователем: mountain_poll.py responses = {} # Установка флага продолжения опроса. polling_active = True while polling_active: # Запрос имени и ответа пользователя. name = input("\nWhat is your name? ") response = input("Which mountain would you like to climb someday? ") # Ответ сохраняется в словаре: responses[name] = response # Проверка продолжения опроса. |