Короткий ответ *args собирает произвольное количество позиционных аргументов в tuple, а kwargs собирает произвольные именованные аргументы в dict — это позволяет писать функции с гибким числом параметров и универсальные обёртки, прозрачно передающие аргументы дальше. Как это работает подробнее При определении функции *args должен идти после обычных позиционных параметров, kwargs — последним. При вызове все "лишние" позиционные аргументы попадают в args как кортеж, все лишние именованные — в kwargs как словарь. При вызове другой функции func(*args, kwargs) происходит обратная операция — распаковка. Пример кода Что использовать на практике Практика. Типичное применение — декораторы и обёртки (logging_wrapper(*args, kwargs)), которые не знают заранее сигнатуру оборачиваемой функции, но должны передать в неё все аргументы как есть. Также используется для функций с опциональными параметрами конфигурации, где явный список был бы слишком длинным. Подводные камни Риски. Злоупотребляют kwargs там, где нужны явные, зад