Короткий ответ
*args и **kwargs — это специальный синтаксис Python для передачи в функцию произвольного числа аргументов. *args собирает все неименованные аргументы в кортеж, а **kwargs — все именованные аргументы в словарь.
Как это работает подробнее
Порядок параметров в сигнатуре строго фиксирован: сначала идут обычные аргументы, затем *args, затем **kwargs.
- Механизм сборки. Когда функция объявлена со звёздочкой, все лишние позиционные аргументы упаковываются в кортеж, а все аргументы вида
ключ=значение— в словарь. - Имена не обязательны.
argsиkwargs— лишь общепринятое соглашение: синтаксически важны звёздочки, поэтому допустимы и*numbers, и**options. - Обратная распаковка. При вызове
func(*seq)разворачивает последовательность в позиционные аргументы, аfunc(**mapping)— словарь в именованные.
Пример кода
Функция с произвольным числом аргументов
def process_data(required_arg, *args, **kwargs):
print(f'Обязательный аргумент: {required_arg}')
print(f'Позиционные аргументы (*args): {args}')
print(f'Именованные аргументы (**kwargs): {kwargs}')
process_data('START', 10, 20, 'go', status='active', user_id=123)
# args = (10, 20, 'go'), kwargs = {'status': 'active', 'user_id': 123}Что использовать на практике
- Гибкие API. Применяй, когда заранее неизвестно количество передаваемых значений, чтобы функция не зависела от конкретной сигнатуры.
- Декораторы. Обёртки почти всегда принимают
*argsи**kwargs, чтобы перехватывать и пробрасывать любые аргументы. - Переопределение методов. В дочернем классе удобно принимать
*argsи**kwargsи передавать их дальше в метод родителя. - Явная сигнатура. Когда набор параметров известен заранее, объявляй их явно — так код читается лучше и меньше шансов на ошибку.
Подводные камни
- Заблуждение про имена. Новички думают, что
argsиkwargs— зарезервированные слова, хотя это лишь соглашение. - Потерянная звёздочка. При вызове легко забыть распаковку: без звёздочки коллекция передастся как один обычный аргумент.
- Злоупотребление. Если сигнатуры всегда строить из
*argsи**kwargs, код перестаёт быть самодокументируемым, а типы аргументов — очевидными.
Как отвечать на собеседовании
- Расскажи, что
*argsсобирает позиционные аргументы в кортеж, а**kwargs— именованные в словарь → приведи пример сигнатуры и вызова функции → упомяни обратную распаковкуfunc(*seq)иfunc(**mapping)→ отметь, что имена могут быть любыми, и назови сценарии: декораторы, проброс в родителя, гибкие API.