Урок 21 из 84 · Основы Python
*args, **kwargs
Содержание урока
Чтобы получить ответ на вопрос в заголовке, разделим его на две части:
- Что такое args и kwargs?
- Что обозначают звездочки?
Начнем с конца. В Python функции в качестве аргумента можно передавать не только отдельные объекты, но также коллекции.
Примечание:
Если функции передается список, то его элементы должны следовать в строго обусловленном заранее порядке, или, другими словами, на своих позициях (иначе как мы узнаем, что собой представляет определенный элемент списка?). Например, если функция sign_up() ждет от нас список [name, age, gender], то мы должны строго соблюдать этот порядок; мы не можем вызвать функцию sign_up(age, name, gender). Такие аргументы называются неименованными или позиционными.
Если же в качестве аргумента функции передается словарь, то порядок следования может быть произвольный, т.к. элементы словаря передаются с ключами, их уже не перепутаешь. Такие аргументы называются
именованными.
Продолжая пример в примечании, обозначим наш список через переменную:
Python
user_data_list = [name, age, gender]
А переменную передадим в функцию:
Python
sign_up(*user_data_list)
При этом, чтобы функция восприняла в качестве аргумента не один объект (а коллекции также являются объектами как и вообще всё в Python), а несколько, коллекцию нужно
распаковать
. Как раз это и делают звездочки. Записи такого типа (с одной или двумя звездочками) в Python используются в двух случаях: при вызове (как мы сделали только что) и при определении функции.
args и *kwargs при определении функции
Аргументы функции в Python, обозначаемые * и ** при определении или вызове, называются
неопределенное количество позиционных или именованных аргументов
. Очень мудрено. На самом деле это
коллекции
- списки, кортежи или словари. Первые два передают позиционные аргументы, словари - именованные аргументы.
Чтобы передать функции несколько аргументов в виде коллекции, коллекцию надо распаковать. Это делается одной или двумя звездочками.
Зададим функцию с одним формальным (позиционным) аргументом и неопределенным количеством дополнительных позиционных аргументов (здесь, два).
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
Функция с именованными аргументами задается так:
Python
>>> 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, будет лучше выбрать более информативные имена (хотя в следующем примере мы не далеко в этом продвинулись =) ):
Python
>>> def print_names(name1, name2, name3):
... print("имя 1:", name1)
... print("имя 2:", name2)
... print("имя 3:", name3)
...
>>> name_list = ("Маша", "Витя")
>>> print_names("Коля", *name_list)
имя 1: Коля
имя 2: Маша
имя 3: Витя
Аргументы можно передавать и так:
Python
>>> print_names(*['Коля', 'Маша', 'Витя'])
имя 1: Коля
имя 2: Маша
имя 3: Витя
Следующий пример показывает вызов функции с именованными аргументами:
Python
>>> name_dic = {"name3": "Витя", "name2": "Маша"}
>>> print_names("Коля", **name_dic)
имя 1: Коля
имя 2: Маша
имя 3: Витя
То же самое с литералом:
Python
>>> print_names(**{'name1': 'Коля', 'name2': 'Маша', 'name3': 'Витя'})
имя 1: Коля
имя 2: Маша
имя 3: Витя
Заключение
Итак, если кратко подытожить вышесказанное, то звездочки в Python используют в следующих случаях:
- При определении функции, если функция принимает неопределенное количество аргументов.
- При вызове функции, когда ей нужно передать несколько объектов в виде коллекции. Обратите внимание, не объект коллекции, а объекты, содержащиеся в коллекции. Таким образом, обозначения
argsи*kwargsраспаковывают коллекцию и передают ее элементы в функцию.