УПРАЖНЕНИЯ
8-6 . Названия городов: напишите функцию city_country(), которая получает название го-
рода и страну . Функция должна возвращать строку в формате “Santiago, Chile” . Вызовите
свою функцию по крайней мере для трех пар «город—страна» и выведите возвращенное
значение .
8-7 . Альбом: напишите функцию make_album(), которая строит словарь с описанием му-
зыкального альбома . Функция должна получать имя исполнителя и название альбома
и возвращать словарь, содержащий эти два вида информации . Используйте функцию
для создания трех словарей, представляющих разные альбомы . Выведите все возвраща-
емые значения, чтобы показать, что информация правильно сохраняется во всех трех
словарях .
Добавьте в make_album() дополнительный параметр для сохранения количества дорожек
в альбоме . Если в строку вызова включено значение количества дорожек, добавьте это зна-
чение в словарь альбома . Создайте как минимум один новый вызов функции с передачей
количества дорожек в альбоме .
8-8 . Пользовательские альбомы: начните с программы из упражнения 8-7 . Напишите цикл
while, в котором пользователь вводит исполнителя и название альбома . Затем в цикле вы-
зывается функция make_album() для введенных пользователей и выводится созданный
словарь . Не забудьте предусмотреть признак завершения в цикле while .
Передача списка
Часто при вызове функции удобно передать список — имен, чисел или более
сложных объектов (например, словарей). При передаче списка функция получает
прямой доступ ко всему его содержимому. Мы воспользуемся функциями для того,
чтобы сделать работу со списком более эффективной.
Допустим, вы хотите вывести приветствие для каждого пользователя из списка.
В следующем примере список имен передается функции
greet_users()
, которая
выводит приветствие для каждого пользователя по отдельности:
greet_users.py
def greet_users(names):
"""Вывод простого приветствия для каждого пользователя в списке."""
for name in names:
msg = "Hello, " + name.title() + "!"
print(msg)
148 Глава 8 • Функции
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
В соответствии со своим определением функция
greet_users()
рассчитывает полу-
чить список имен, который сохраняется в параметре
names
. Функция перебирает
полученный список и выводит приветствие для каждого пользователя. В точке
мы определяем список пользователей
usernames
, который затем передается
greet_
users()
в вызове функции:
Hello, Hannah!
Hello, Ty!
Hello, Margot!
Результат выглядит именно так, как ожидалось. Каждый пользователь получает
персональное сообщение, и эту функцию можно вызвать для каждого нового на-
бора пользователей.
Изменение списка в функции
Если вы передаете список функции, код функции сможет изменить список. Все
изменения, внесенные в список в теле функции, закрепляются, что позволяет эф-
фективно работать со списком даже при больших объемах данных.
Допустим, компания печатает на 3D-принтере модели, предоставленные пользо-
вателем. Проекты хранятся в списке, а после печати перемещаются в отдельный
список. В следующем примере приведена реализация, не использующая функции:
printing_models.py
# Список моделей, которые необходимо напечатать.
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []
# Цикл последовательно печатает каждую модель до конца списка.
# После печати каждая модель перемещается в список completed_models.
while unprinted_designs:
current_design = unprinted_designs.pop()
# Печать модели на 3D-принтере.
print("Printing model: " + current_design)
completed_models.append(current_design)
# Вывод всех готовых моделей.
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
В начале программы создается список моделей и пустой список
completed_models
,
в который каждая модель перемещается после печати. Пока в
unprinted_designs
остаются модели, цикл
while
имитирует печать каждой модели: модель удаляется
с конца списка, сохраняется в
current_design
, а пользователь получает сообщение
о том, что текущая модель была напечатана. Затем модель перемещается в спи-
сок напечатанных. После завершения цикла выводится список напечатанных
моделей:
Передача списка 149
Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case
The following models have been printed:
dodecahedron
robot pendant
iphone case
Мы можем изменить структуру этого кода: для этого следует написать две функ-
ции, каждая из которых решает одну конкретную задачу. Бульшая часть кода
останется неизменной; просто программа становится более эффективной. Первая
функция занимается печатью, а вторая выводит сводку напечатанных моделей:
def print_models(unprinted_designs, completed_models):
"""
Имитирует печать моделей, пока список не станет пустым.
Каждая модель после печати перемещается в completed_models.
"""
while unprinted_designs:
current_design = unprinted_designs.pop()
# Имитация печати модели на 3D-принтере.
print("Printing model: " + current_design)
completed_models.append(current_design)
def show_completed_models(completed_models):
"""Выводит информацию обо всех напечатанных моделях."""
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
В точке определяется функция
print_models()
с двумя параметрами: список
моделей для печати и список готовых моделей. Функция имитирует печать каж-
дой модели, последовательно извлекая модели из первого списка и перемещая
их во второй список. В точке определяется функция
show_completed_models()
с одним параметром: списком напечатанных моделей. Функция
show_completed_
models()
получает этот список и выводит имена всех напечатанных моделей.
Программа выводит тот же результат, что и версия без функций, но структура
кода значительно улучшилась. Код, выполняющий бульшую часть работы, разне-
сен по двум разным функциям; это упрощает чтение основной части программы.
Теперь любому разработчику будет намного проще просмотреть код программы
и понять, что делает программа:
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
150 Глава 8 • Функции
Программа создает список моделей для печати и пустой список для готовых моде-
лей. Затем, поскольку обе функции уже определены, остается вызвать их и передать
правильные аргументы. Мы вызываем
print_models()
и передаем два необходимых
списка; как и ожидалось,
print_models()
имитирует печать моделей. Затем вызыва-
ется функция
show_completed_models()
, и ей передается список готовых моделей,
чтобы функция могла вывести информацию о напечатанных моделях. Благодаря
содержательным именам функций другой разработчик сможет прочитать этот код
и понять его даже без комментариев.
Вдобавок эта программа создает меньше проблем с расширением и сопровождени-
ем, чем версия без функций. Если позднее потребуется напечатать новую партию
моделей, достаточно снова вызвать
print_models()
. Если окажется, что код печати
необходимо модифицировать, изменения достаточно внести в одном месте, и они
автоматически распространятся на все вызовы функции. Такой подход намного
эффективнее независимой правки кода в нескольких местах программы.
Этот пример также демонстрирует принцип, в соответствии с которым каждая
функция должна решать одну конкретную задачу. Первая функция печатает
каждую модель, а вторая выводит информацию о готовых моделях. Такой подход
предпочтительнее решения обеих задач в функции. Если вы пишете функцию
и видите, что она решает слишком много разных задач, попробуйте разделить ее
код на две функции.
Помните, что функции всегда можно вызывать из других функций. Эта возмож-
ность может пригодиться для разбиения сложных задач на серию составляющих.
Запрет изменения списка в функции
Иногда требуется предотвратить изменение списка в функции. Допустим, у вас
имеется список моделей для печати, и вы пишете функцию для перемещения их
в список готовых моделей, как в предыдущем примере. Возможно, даже после пе-
чати всех моделей исходный список нужно оставить для отчетности. Но, поскольку
все имена моделей были перенесены из списка
unprinted_designs
, остался только
пустой список; исходная версия списка потеряна. Проблему можно решить пере-
дачей функции копии списка вместо оригинала. В этом случае все изменения,
вносимые функцией в список, будут распространяться только на копию, а оригинал
списка остается неизменным.
Чтобы передать функции копию списка, можно поступить так:
Достарыңызбен бөлісу: |