До настоящего момента мы работали только с одним фрагментом информации, полученной от пользователя. Мы получали ввод пользователя, а затем выводили ответ на него. При следующем проходе цикла while программа получала новое входное значение и реагировала на него. Но, чтобы работать с несколькими фрагментами информации, необходимо использовать в циклах while списки и словари.
Цикл for хорошо подходит для перебора списков, но, скорее всего, список не должен изменяться в цикле, потому что у Python возникнут проблемы с отслеживанием элементов. Чтобы изменять список в процессе обработки, используйте цикл while. Использование циклов while со списками и словарями позволяет собирать, хранить и упорядочивать большие объемы данных для последующего анализа и обработки.
Возьмем список недавно зарегистрированных, но еще не проверенных пользователей сайта. Как переместить пользователей после проверки в отдельный список проверенных пользователей? Одно из возможных решений: используем цикл while для извлечения пользователей из списка непроверенных, проверяем их и включаем в отдельный список проверенных пользователей. Код может выглядеть так:
confirmed_users.py
# Начинаем с двух списков: пользователей для проверки
# и пустого списка для хранения проверенных пользователей.
(1) unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []
# Проверяем каждого пользователя, пока остаются непроверенные
# пользователи. Каждый пользователь, прошедший проверку,
# перемещается в список проверенных.
(2)while unconfirmed_users:
(3) . .current_user = unconfirmed_users.pop()
. .
. .print("Verifying user: " + current_user.title())
(4) . .confirmed_users.append(current_user)
# Вывод всех проверенных пользователей.
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
. .print(confirmed_user.title())
Работа программы начинается с двух списков: непроверенных пользователей (1) и пустого списка для проверенных пользователей. Цикл while в точке (2) выполняется, пока в списке unconfirmed_users остаются элементы. Внутри этого списка функция pop() в точке (3) извлекает очередного непроверенного пользователя с конца списка unconfirmed_users. В данном примере список unconfirmed_users завершается пользователем Candace; это имя первым извлекается из списка, сохраняется в current_user и добавляется в список confirmed_users в точке (4). Далее следуют пользователи Brian и Alice.
Программа моделирует проверку каждого пользователя выводом сообщения, после чего переносит пользователя в список проверенных. По мере сокращения списка непроверенных пользователей список проверенных пользователей растет. Когда в списке непроверенных пользователей не остается ни одного элемента, цикл останавливается, и выводится список проверенных пользователей:
Verifying user: Candace
Verifying user: Brian
Verifying user: Alice
The following users have been confirmed:
Candace
Brian
Alice
Удаление всех вхождений конкретного значения из списка
В главе 3 функция remove() использовалась для удаления конкретного значения из списка. Функция remove() работала, потому что интересующее нас значение встречалось в списке только один раз. Но что если вы захотите удалить все вхождения значения из списка?
Допустим, имеется список 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:
. .# Запрос имени и ответа пользователя.
(1) . .name = input("\nWhat is your name? ")
. .response = input("Which mountain would you like to climb someday? ")
. .
. .# Ответ сохраняется в словаре:
(2) . .responses[name] = response
. .
. .# Проверка продолжения опроса.
(3) . .repeat = input("Would you like to let another person respond? (yes/ no) ")
. .if repeat == 'no':
. . . .polling_active = False
. . . .
# Опрос завершен, вывести результаты.
print("\n--- Poll Results ---")
(4)for name, response in responses.items():
. .print(name + " would like to climb " + response + ".")
Сначала программа определяет пустой словарь (responses) и устанавливает флаг (polling_active), показывающий, что опрос продолжается. Пока polling_active содержит True, Python будет выполнять код в цикле while.
В цикле пользователю предлагается ввести имя и название горы, на которую ему хотелось бы подняться (1) . Эта информация сохраняется в словаре responses в строке (2), после чего программа спрашивает у пользователя, нужно ли продолжать опрос (3). Если пользователь отвечает положительно, то программа снова входит в цикл while. Если же ответ отрицателен, флаг polling_active переходит в состояние False, цикл while перестает выполняться, и завершающий блок кода (4) выводит результаты опроса.
Если вы запустите эту программу и введете пару ответов, результат будет выглядеть примерно так:
What is your name? Eric
Which mountain would you like to climb someday? Denali
Would you like to let another person respond? (yes/ no) yes
What is your name? Lynn
Which mountain would you like to climb someday? Devil's Thumb
Would you like to let another person respond? (yes/ no) no
--- Poll Results ---
Lynn would like to climb Devil's Thumb.
Eric would like to climb Denali.
Упражнения
7-8. Сэндвичи: создайте список с именем sandwich_orders, заполните его названиями различных видов сэндвичей. Создайте пустой список с именем finished_sandwiches. В цикле переберите элементы первого списка и выведите сообщение для каждого элемента (например, «I made your tuna sandwich»). После этого каждый сэндвич из первого списка перемещается в список finished_sandwiches. После того как все элементы первого списка будут обработаны, выведите сообщение с перечислением всех изготовленных сэндвичей.
7-9. Без пастрами: используя список sandwich_orders из упражнения 7-8, проследите за тем, чтобы значение ‘pastrami’ встречалось в списке как минимум три раза. Добавьте в начало программы код для вывода сообщения о том, что пастрами больше нет, и напишите цикл while для удаления всех вхождений ‘pastrami’ из sandwich_orders. Убедитесь в том, что в finished_sandwiches значение ‘pastrami’ не встречается ни одного раза.
7-10. Отпуск мечты: напишите программу, которая опрашивает пользователей, где бы они хотели провести отпуск. Включите блок кода для вывода результатов опроса.
Итоги
В этой главе вы научились использовать input() для того, чтобы пользователи могли вводить собственную информацию в своих программах. Вы научились работать с числовыми и текстовыми данными, а также управлять продолжительностью выполнения своих программ с помощью циклов while. Также мы рассмотрели несколько способов управления циклами while: установку флага, команду break и команду continue. Вы узнали, как использовать цикл while для перемещения элементов из одного списка в другой и как удалить все вхождения некоторого значения из списка. Также были рассмотрены возможности применения циклов while со словарями.
Глава 8 посвящена функциям. Функции позволяют разделить программу на меньшие части, каждая из которых решает одну конкретную задачу. Функции можно хранить в отдельных файлах и вызывать их столько раз, сколько потребуется. Благодаря функциям вы сможете писать более эффективный код, более простой в отладке и сопровождении, который к тому же можно повторно использовать в разных программах.
8. Функции
Эта глава посвящена функциям — именованным блокам кода, предназначенным для решения одной конкретной задачи. Чтобы выполнить задачу, определенную в виде функции, вы указываете имя функции, отвечающей за эту задачу. Если задача должна многократно выполняться в программе, вам не придется заново вводить весь необходимый код; просто вызовите функцию, предназначенную для решения задачи, и этот вызов приказывает Python выполнить код, содержащийся внутри функции. Как вы вскоре убедитесь, использование функций упрощает чтение, написание, тестирование кода и исправление ошибок.
В этой главе также рассматриваются возможности передачи информации функциям. Вы узнаете, как писать функции, основной задачей которых является вывод информации, и другие функции, предназначенные для обработки данных и возвращения значения (или набора значений.) Наконец, вы научитесь хранить функции в отдельных файлах, называемых модулями, для упорядочения файлов основной программы.