ПрограммированиеPython разработчик

Поясните, как работают аргументы *args и **kwargs в функциях Python. Для чего используются, чем опасны при неправильном применении и как их правильно комбинировать с обычными и именованными аргументами?

Проходите собеседования с ИИ помощником Hintsage

Ответ

*args — собирает произвольное количество позиционных аргументов в кортеж.

**kwargs — собирает произвольное количество именованных аргументов (ключ=значение) в словарь.

Это позволяет писать функции с гибким интерфейсом:

def my_func(a, b, *args, **kwargs): print(a, b) print(args) print(kwargs) my_func(1, 2, 3, 4, x=10, y=20) # 1 2 # (3, 4) # {'x': 10, 'y': 20}

Тонкости:

  • Обычные аргументы идут первыми, затем *args, после именованные с значениями по умолчанию, и **kwargs — строго в таком порядке при объявлении функции.
  • Через * можно "распаковать" последовательности, а через ** — словари при вызове функции.
  • Нельзя повторно задавать одни и те же параметры — будет ошибка TypeError.

Вопрос с подвохом

Можно ли поменять порядок *args и именованных аргументов со значением по умолчанию, например:

def foo(a, *args, x=10, **kwargs): pass

или обязательно всегда ставить значения по умолчанию после *args?

Ответ:

В Python 3 можно! Вот так (не работало в Python 2):

def foo(a, *args, x=10): pass

Параметры после *args ("keyword-only arguments") могут иметь значения по умолчанию или быть обязательными — их можно задавать только по имени.

Примеры реальных ошибок из-за незнания тонкостей темы


История

Передача неправильных аргументов через *args/**kwargs

В сервисах REST API автоматизация маршалинга данных строилась через **kwargs. Лишний параметр не был замечен — функция принимала неожиданное значение в kwargs, что приводило к потере контрольной логики и трудным для отладки багам.


История

Дублирование именованных аргументов

При вызове функции разработчик случайно указал параметр и явно, и через **kwargs, например: my_func(a=1, **{"a": 2}). В результате — TypeError и падение сервиса.


История

Забыли позиционные или именованные только аргументы

При написании декоратора неправильная передача параметров (не соблюден порядок и структура) приводила к тому, что оригинальная функция получала не то количество аргументов, соглашения о которых менялись, и в продакшене начали возникать ошибки вызова TypeError.