Вероятно, при чтении документации к функциям вам случалось увидеть странные параметры – *args и **kwargs. Например, function(params, *args, **kwargs)
. И возможно, вы интересовались, что это за параметры.
В этой статье мы разберем, что собой представляют *args и **kwargs, а также рассмотрим примеры их применения.
Введение
С помощью функций в Python мы можем писать переиспользуемый код для выполнения определенных задач.
Давайте определим функцию, которая печатает имена киношных персонажей.
def characters(name1, name2, name3): print(name1, name2, name3) characters("Iron Man", "Black Panther", "Captain America") # Вывод: # Iron Man Black Panther Captain America
Функция characters
принимает 3 позиционных аргумента – name1
, name2
, name3
– и просто печатает переданные ей данные.
Но что будет, если мы передадим не три аргумента, а больше? Скажем, четыре?
def characters(name1, name2, name3): print(name1, name2, name3) characters("Iron Man", "Black Panther", "Captain America", "Hulk") # Вывод: # TypeError: characters() takes 3 positional arguments but 4 were given
Мы получим ошибку TypeError.
Ошибка возникает из-за лишнего аргумента, переданного в функцию, которая принимает только три аргумента.
Чтобы код выполнялся без ошибок, нужно добавить еще один параметр в определении функции.
Однако это не самый лучший метод. Допустим, что вы работаете над проектом, в котором вам нужно динамически добавлять аргументы при вызове определенной функции.
Что делать в таких ситуациях? Решение есть!
Использование *args
“args” – это просто сокращение от arguments (русск. аргументы). *args используется в качестве параметра, когда мы не уверены, сколько аргументов нужно передать в функцию.
*args
– это позиционный параметр.
Звездочка (*) перед args
означает, что аргумент имеет переменную длину. Используя *args
, при вызове функции можно передать любое количество аргументов.
Рассмотрим пример:
def friends(*args): print(args) friends("Sachin", "Rishu", "Yashwant", "Abhishek") # Вывод: # ('Sachin', 'Rishu', 'Yashwant', 'Abhishek')
Мы получили кортеж, потому что при использовании *args
функция получит аргументы в виде кортежа.
Давайте проверим тип args
:
def friends(*args): print(type(args)) print(args) friends("Sachin", "Rishu", "Yashwant", "Abhishek") # Вывод: # <class 'tuple'> # ('Sachin', 'Rishu', 'Yashwant', 'Abhishek')
При определении функции вместе с *args
можно использовать и другие параметры. Пример:
def friends(greet, *args): for friend in args: print(f"{greet} to Python, {friend}") greet = "Welcome" friends(greet, "Sachin", "Rishu", "Yashwant", "Abhishek")
Вывод:
Welcome to Python, Sachin Welcome to Python, Rishu Welcome to Python, Yashwant Welcome to Python, Abhishek
Примечание: вместо “args” можно использовать любое имя, включая кличку вашего питомца, имя друга или даже имя вашей девушки, если перед ним поставить символ *.
Давайте вместо args
используем другое имя:
def dog(prefix, *german_shepherd): for breed in german_shepherd: print(f"The {prefix} is {breed}.") prefix = "breed" dog(prefix, "Labrador", "GSD", "Chihuahua")
Вывод:
The breed is Labrador. The breed is GSD. The breed is Chihuahua.
Важное примечание: если помимо *args
вы передаете в фукнцию и обычные аргументы, при объявлении функции параметр *args
должен идти после обычных.
Давайте для примера попробуем поставить *args
перед обычным параметром:
def heroes(*characters, country): for character in characters: print(f"{character} is from {country}.") country = "USA" heroes(country, "Iron Man", "Captain America", "Spiderman") # Вывод: # TypeError: heroes() missing 1 required keyword-only argument: 'country'
Мы получили ошибку TypeError.
Но если мы изменим код и поменяем местами параметры в объявлении функции, ошибка не возникнет:
def heroes(country, *characters): for character in characters: print(f"{character} is from {country}.") country = "USA" heroes(country, "Iron Man", "Captain America", "Spiderman")
Вывод:
Iron Man is from USA. Captain America is from USA. Spiderman is from USA.
Использование **kwargs
“kwargs” – это сокращение от keyword arguments (русск. “аргументы с ключевыми словами”, обычно переводится как “именованные аргументы”).
**kwargs
работает так же, как и *args
. Но, в отличие от *args
, **kwargs
принимает не позиционные, а именованные аргументы.
В **kwargs
мы используем двойную звездочку **, которая позволяет нам передавать именованные аргументы.
Пример использования **kwargs
:
def hello(**kwargs): print(type(kwargs)) for key, value in kwargs.items(): print(f"{key} is {value}.") hello(One = "Red", two = "Green", three = "Blue")
Вывод:
<class 'dict'> One is Red. two is Green. three is Blue.
Тип **kwargs
– словарь, то есть аргументы передаются в виде пар ключ-значение.
Как и *args
, **kwargs
можно использовать совместно с обычными аргументами. Пример:
def hello(write, **kwargs): print(write) for key, value in kwargs.items(): print(f"{key} is {value}.") write = "RGB stands for:" hello(write, One = "Red", two = "Green", three = "Blue")
Вывод:
RGB stands for: One is Red. two is Green. three is Blue.
Также вместо **kwargs
можно использовать любое другое имя:
def hello(write, **color): print(write) for key, value in color.items(): print(f"{key} is {value}.") write = "RGB stand for:" hello(write, One = "Red", two = "Green", three = "Blue")
Вывод:
RGB stand for: One is Red. two is Green. three is Blue.
Примечание: нельзя передавать **kwargs
перед *args
в определении функции, иначе получим SyntaxError.
По правилам порядок должен быть таким: function(params, *args, **kwargs)
. Т.е. сначала идут обычные параметры, потом *args
, потом **kwargs
.
Пример использования обычных параметров вместе с *args и **kwargs
При определении функции мы можем использовать все три типа параметров.
def friends(greet, *args, **kwargs): for names in args: print(f"{greet} to the Programming zone {names}") print("\nI am Veronica and I would like to announce your roles:") for key, value in kwargs.items(): print(f"{key} is a {value}") greet = "Welcome" names = ["Sachin", "Rishu", "Yashwant", "Abhishek"] roles = {"Sachin":"Chief Instructor", "Rishu":"Engineer", "Yashwant":"Lab Technician", "Abhishek":"Marketing Manager"} friends(greet, *names, **roles)
Вывод:
Welcome to the Programming zone Sachin Welcome to the Programming zone Rishu Welcome to the Programming zone Yashwant Welcome to the Programming zone Abhishek I am Veronica and I would like to announce your roles: Sachin is a Chief Instructor Rishu is a Engineer Yashwant is a Lab Technician Abhishek is a Marketing Manager
Вы, верно, заметили, что в приведенном выше коде использовались переменные names
и roles
. Однако мы поставили * перед переменной names
и ** перед переменной roles
, когда передавали их в функцию.
* и ** – это операторы распаковки.
Оператор распаковки
Эти операторы очень полезны, как вы видели выше.
Одинарная звездочка (*) используется для распаковки итерируемых объектов, а двойная звездочка (**) – для распаковки словаря.
Операторы * и ** позволяют выполнять распаковку в вызовах функций, в представлениях (comprehensions) и генераторных выражениях (источник).
Заключение
Теперь, зная, что собой представляют *args и **kwargs в параметрах функций, вы можете попробовать применить их в собственном коде.
Эти параметры могут пригодиться вам при работе над проектами, в которых данные поступают в функцию динамически, и вы не знаете, сколько аргументов нужно передать.
Перевод статьи “Understanding args and kwargs in Python: Best Practices and Guide”.