Основы функций. 2 часть
Limera1n
Чтобы плавно подвести к еще одной важной теме касающейся функций давайте предположим, что у нас есть функция, которая принимает на вход некие доходы, полученные несколькими переводами, а мы хотим с них посчитать налоги:

В sum мы передали tuple. Получаем правильный результат. Однако смотрите, какая есть проблема, ведь этой функцией может захотеть воспользоваться другой программист, предположим, что эту функцию мы хотим переиспользовать. Но что делать, если этих самых транзакций будет не 3, а 4? Мы не можем передать еще один аргумент, будет ошибка. Мы можем написать еще одну функцию, которая будет принимать и p4, и соответственно можем передавать теперь 4 аргумента. И это будет работать. Но что, если требуется пятый, шестой, седьмой? Да, мы можем принимать list, однако есть еще один способ, иногда более красивый с точки зрения вызова, делается это с помощью специального синтаксиса проставления звездочки * :

Здесь мы после звездочки ставим args, это именование данного аргумента, его не обязательно именовать именно args, но это некое соглашение между программистами именовать его именно args. Сделали цикл, когда после прохождения по каждому элементу будет выдаваться Got payment = ***, что свидетельствует о том, что мы якобы получили транзакцию.
И другой похожий случай, когда мы хотим передать n элементов в виде пар ключ:значение. Для этого используется две звездочки и именование аргумента kwargs, он означает "аргументы ключевого слова".

(**kwargs) это означает, что сюда передаются n пар ключ:значение. Так же пробежались по ним циклом. Таким способом мы можем передавать ключи:значения и они нормально воспринимаются. Вызываем функцию items, раскладываем возврат на ключ k и значение v, и собственно их выводим.
Так же бывают функции, которые сочетают в себе оба варианта *args и **kwargs. Но это используется очень редко. А вид будет такой:
def func_important(*args, **kwargs)
Это все базовая часть, так сказать. Дальше посмотрим на более интересные штуки, связанные с функциями.