Использование произвольного набора именованных аргументов

Иногда программа должна получать произвольное количество аргументов, но вы не знаете заранее, какая информация будет передаваться функции. В таких случаях можно написать функцию, получающую столько пар «ключ—значение», сколько указано в команде вызова. Один из возможных примеров — построение пользовательских профилей: вы знаете, что вы получите информацию о пользователе, но не знаете заранее, какую именно. Функция build_profile() в следующем примере всегда получает имя и фамилию, но также может получать произвольное количество именованных аргументов:

user_profile.py

def build_profile(first, last, **user_info):

. ."""Строит словарь с информацией о пользователе."""

. .profile = {}

(1) . .profile['first_name'] = first

. .profile['last_name'] = last

(2) . .for key, value in user_info.items():

. . . .profile[key] = value

. .return profile

user_profile = build_profile('albert', 'einstein',

. . . . . . . . . . . . . . location='princeton',

. . . . . . . . . . . . . . field='physics')

print(user_profile)

Определение build_profile() ожидает получить имя и фамилию пользователя, а также позволяет передать любое количество пар «имя—значение». Две звездочки перед параметром **user_info заставляют Python создать пустой словарь с именем user_info и упаковать в него все полученные пары «имя—значение». Внутри функции вы можете обращаться к парам «имя–значение» из user_info точно так же, как в любом словаре.

В теле build_profile() создается пустой словарь с именем profile для хранения профиля пользователя. В точке (1) в словарь добавляется имя и фамилия, потому что эти два значения всегда передаются пользователем. В точке (2) функция перебирает дополнительные пары «ключ—значение» в словаре user_info и добавляет каждую пару в словарь profile. Наконец, словарь profile возвращается в точку вызова функции.

Вызовем функцию build_profile() и передадим ей имя 'albert', фамилию 'einstein', и еще две пары «ключ—значение» location='princeton' и field='physics'. Программа сохраняет возвращенный словарь в user_profile и выводит его содержимое:

{'first_name': 'albert', 'last_name': 'einstein',

'location': 'princeton', 'field': 'physics'}

Возвращаемый словарь содержит имя и фамилию пользователя, а в данном случае еще и местонахождение и область исследований. Функция будет работать, сколько бы дополнительных пар «ключ—значение» ни было передано при вызове функции.

При написании функций допускаются самые разнообразные варианты смешения позиционных, именованных и произвольных значений. Полезно знать о существовании всех этих типов аргументов, потому что они часто будут встречаться вам при чтении чужого кода. Только с опытом вы научитесь правильно использовать разные типы аргументов и поймете, когда следует применять каждый тип; а пока просто используйте самый простой способ, который позволит решить задачу. С течением времени вы научитесь выбирать наиболее эффективный вариант для каждой конкретной ситуации.

Упражнения

8-12. Сэндвичи: напишите функцию, которая получает список компонентов сэндвича. Функция должна иметь один параметр для любого количества значений, переданных при вызове функции, и выводить описание заказанного сэндвича. Вызовите функцию три раза с разными количествами аргументов.

8-13. Профиль: начните с копии программы user_profile.py. Создайте собственный профиль вызовом build_profile(), укажите имя, фамилию и три другие пары «ключ—значение» для вашего описания.

8-14. Автомобили: напишите функцию для сохранения информации об автомобиле в словаре. Функция всегда должна возвращать производителя и название модели, но при этом она может получать произвольное количество именованных аргументов. Вызовите функцию с передачей обязательной информации и еще двух пар «имя—значение» (например, цвет и комплектация). Ваша функция должна работать для вызовов следующего вида:

car = make_car(‘subaru’, ‘outback’, color=’blue’, tow_package=True)

Выведите возвращаемый словарь и убедитесь в том, что вся информация была сохранена правильно.