Молодогвардейцев 454015 Россия, Челябинская область, город Челябинск 89085842764
MindHalls logo

Упаковка и распаковка аргументов функции в Python

Язык программирования Python очень занимательный. Гвидо Ван Россум душу вложил ради того, чтобы создать максимально высокоуровневый, но в то же время простой и понятный язык. Необязательно штудировать тонну литературы ради того, чтобы написать что нибудь поинтереснее , чем «Привет мир». Язык таит в себе очень много фишек, которые волей-неволей постепенно изучаешь, и твой код становится красивым и производительным. Недавно мне открылась одна очень интересная особенность языка, которой я хочу сейчас поделиться.

Представим ситуацию. Мы пишем функцию summ(), которая, как нетрудно догадаться из названия, считаем сумму элементов. Сколько входных аргументов ей определить? Можно два, а можно три, в зависимости от требований алгоритма. А если нужно посчитать сначала сумму двух, а потом трех? Две разные функции писать не хочется. Очевидное решение, которое приходит в голову — передать в качестве аргумента массив элементов.

Однако не торопитесь! Чем плохо передавать в функцию просто list? А тем, что список — это изменяемая коллекция! Согласитесь, что неправильно функции менять свои аргументы? Это может привести к недопонимаю и ошибкам. Конечно, если речь не идет о разного рода функциях форматирования, цель которых именно изменить входной массив. Хотя даже в этой ситуации правильнее было бы вернуть отформатированный массив, а старый оставить как есть. Но в случае подсчета суммы нам точно нельзя изменять входные данные. Именно поэтому упаковка и распаковка аргументов идеально подходит в таких ситуациях.

Упаковка аргументов в Python

Синтаксис простой:

def summ(*elements):
    ....

Внимание всем фанатам С/С++! Это не указатель, я понимаю, как вам тяжело это принять. Но я же справился, значит и вы сможете 🙂

Это работает следующим образом. Питон анализирует вызов функции summ и складывает aka упаковывает все аргументы в кортеж elements. Кортеж выбран не случайно. Для того, чтобы обеспечить неизменяемость аргументов, о которой я говорил выше. Посмотрим на примере.

Пример

def summ(*elements):
    #здесь эти элементы автоматически упакуются в кортеж
    result = 0

    for element in elements:
        result += element

    return result

#передаем три элемента в функцию
print(summ(1, 2, 3))

#можно передавать сколько угодно элементов
print(summ(1, 2, 3, 122, 5000, 10, -1, -5434))

Распаковка аргументов в Python

Здорово, мы научили функцию принимать сколь угодно много аргументов, но их же неудобно передавать через запятую, верно? Для этого существует распаковка аргументов. Это возможность, грубо говоря, подать элементы коллекции на вход функции через запятую. Другими словами, отправить аргументом не сам list или set, а его элементы через запятую, один элемент — один аргумент.

Пример

#распаковка работает для любых объектов, поддерживающих итераторы
mas = [1, 2, 3, 4, 5]
summ(*mas) #такой вызов эквивалентен вызову summ(1, 2, 3, 4, 5)

Заключение

Термины можно очень легко запомнить. Запаковка используется всегда в функции, потому что она «запаковывает» все аргументы в один кортеж. Распаковка, соответственно, используется при вызове функции и «распаковывает» элементы из любой коллекции, которая поддерживает итерацию.

Но необходимо сделать небольшое замечание. Плохим тоном является использование распаковки к коллекции set. Причиной служит случайное расположение элементов во множестве, из-за этого вы не можете гарантировать последовательность аргументов при передаче, а это плохо.

Python очень крутой, чем больше я на нем пишу, тем больше нахожу интересных особенностей. Такого не было с C/C++. Я имею ввиду, что не было желания копать в глубь языка, находить новые фишечки. А копаться в питоне одно удовольствие. На этом все, спасибо за внимание!