Что такое *args и **kwargs в Python

Что такое *args и **kwargs в Python
  • Опубликовано:
  • Теги: python

... или как использовать переменное количество аргументов в Python

Чтобы получить ответ на вопрос в заголовке, разделим его на две части:
  1. Что такое args и kwargs? (самые нетерпеливые могут подсмотреть ответ =) )
  2. Что обозначают звездочки?
Начнем с конца. В Python функции в качестве аргумента можно передавать не только отдельные объекты, но также коллекции.

Примечание:
Если функции передается список, то его элементы должны следовать в строго обусловленном заранее порядке, или, другими словами, на своих позициях (иначе как мы узнаем, что собой представляет определенный элемент списка?). Например, если функция sign_up() ждет от нас список [name, age, gender], то мы должны строго соблюдать этот порядок; мы не можем вызвать функцию sign_up(age, name, gender). Такие аргументы называются неименованными или позиционными.
Если же в качестве аргумента функции передается словарь, то порядок следования может быть произвольный, т.к. элементы словаря передаются с ключами, их уже не перепутаешь. Такие аргументы называются именованными.

Продолжая пример в примечании, обозначим наш список через переменную:
user_data_list = [name, age, gender]
А переменную передадим в функцию:
sign_up(*user_data_list)
При этом, чтобы функция восприняла в качестве аргумента не один объект (а коллекции также являются объектами как и вообще всё в Python), а несколько, коллекцию нужно распаковать. Как раз это и делают звездочки. Записи такого типа (с одной или двумя звездочками) в Python используются в двух случаях: при вызове (как мы сделали только что) и при определении функции.

*args и **kwargs при определении функции

Аргументы функции в Python, обозначаемые * и ** при определении или вызове, называются неопределенное количество позиционных или именованных аргументов. Очень мудрено. На самом деле это коллекции - списки, кортежи или словари. Первые два передают позиционные аргументы, словари - именованные аргументы.
Чтобы передать функции несколько аргументов в виде коллекции, коллекцию надо распаковать. Это делается одной или двумя звездочками.
Зададим функцию с одним формальным (позиционным) аргументом и неопределенным количеством дополнительных позиционных аргументов (здесь, два).
>>> def test_var_args(farg, *args):
...     print("formal arg:", farg)
...     for arg in args:
...         print("another arg:", arg)
...
>>> test_var_args(1, "two", 3)
formal arg: 1
another arg: two
another arg: 3
Функция с именованными аргументами задается так:
>>> def test_var_kwargs(farg, **kwargs):
...     print("formal arg:", farg)
...     for key in kwargs:
...         print("another keyword arg: %s: %s" % (key, kwargs[key]))
...
>>> test_var_kwargs(farg=1, myarg2="two", myarg3=3)
formal arg: 1
another keyword arg: myarg2: two
another keyword arg: myarg3: 3

Так что же такое args и kwargs?!!

Теперь вы готовы усвоить всю правду об этом :)
Имена args и kwargs по негласному соглашению принято использовать в документации Python. На самом деле никто не запрещает брать любые другие валидные имена переменных. Например, для словарей наряду c **kwargs иногда используют **options.

Применение * и ** при вызове функции

Теперь посмотрим как вызывать функцию с позиционными аргументами (уже демонстрировали выше). Здесь уже меньше смысла в args и kwargs, будет лучше выбрать более информативные имена (хотя в следующем примере мы не далеко в этом продвинулись =) ):
>>> def print_names(name1, name2, name3):
...     print("имя 1:", name1)
...     print("имя 2:", name2)
...     print("имя 3:", name3)
...
>>> name_list = ("Маша", "Витя")
>>> print_names("Коля", *name_list)
имя 1: Коля
имя 2: Маша
имя 3: Витя
Аргументы можно передавать и так:
>>> print_names(*['Коля', 'Маша', 'Витя'])
имя 1: Коля
имя 2: Маша
имя 3: Витя
Следующий пример показывает вызов функции с именованными аргументами:

>>> name_dic = {"name3": "Витя", "name2": "Маша"}
>>> print_names("Коля", **name_dic)
имя 1: Коля
имя 2: Маша
имя 3: Витя
То же самое с литералом:
>>> print_names(**{'name1': 'Коля', 'name2': 'Маша', 'name3': 'Витя'})
имя 1: Коля
имя 2: Маша
имя 3: Витя

Заключение

Итак, если кратко подытожить вышесказанное, то звездочки в Python используют в следующих случаях:

  1. При определении функции, если функция принимает неопределенное количество аргументов.
  2. При вызове функции, когда ей нужно передать несколько объектов в виде коллекции. Обратите внимание, не объект коллекции, а объекты, содержащиеся в коллекции. Таким образом, обозначения *args и **kwargs распаковывают коллекцию и передают ее элементы в функцию.